1# Copyright 2016 Google Inc. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Unit tests for oauth2client._pure_python_crypt.""" 16 17import os 18 19import mock 20from pyasn1_modules import pem 21import rsa 22import six 23import unittest2 24 25from oauth2client import _helpers 26from oauth2client import _pure_python_crypt 27from oauth2client import crypt 28 29 30class TestRsaVerifier(unittest2.TestCase): 31 32 PUBLIC_KEY_FILENAME = os.path.join(os.path.dirname(__file__), 33 'data', 'privatekey.pub') 34 PUBLIC_CERT_FILENAME = os.path.join(os.path.dirname(__file__), 35 'data', 'public_cert.pem') 36 PRIVATE_KEY_FILENAME = os.path.join(os.path.dirname(__file__), 37 'data', 'privatekey.pem') 38 39 def _load_public_key_bytes(self): 40 with open(self.PUBLIC_KEY_FILENAME, 'rb') as fh: 41 return fh.read() 42 43 def _load_public_cert_bytes(self): 44 with open(self.PUBLIC_CERT_FILENAME, 'rb') as fh: 45 return fh.read() 46 47 def _load_private_key_bytes(self): 48 with open(self.PRIVATE_KEY_FILENAME, 'rb') as fh: 49 return fh.read() 50 51 def test_verify_success(self): 52 to_sign = b'foo' 53 signer = crypt.RsaSigner.from_string(self._load_private_key_bytes()) 54 actual_signature = signer.sign(to_sign) 55 56 verifier = crypt.RsaVerifier.from_string( 57 self._load_public_key_bytes(), is_x509_cert=False) 58 self.assertTrue(verifier.verify(to_sign, actual_signature)) 59 60 def test_verify_unicode_success(self): 61 to_sign = u'foo' 62 signer = crypt.RsaSigner.from_string(self._load_private_key_bytes()) 63 actual_signature = signer.sign(to_sign) 64 65 verifier = crypt.RsaVerifier.from_string( 66 self._load_public_key_bytes(), is_x509_cert=False) 67 self.assertTrue(verifier.verify(to_sign, actual_signature)) 68 69 def test_verify_failure(self): 70 verifier = crypt.RsaVerifier.from_string( 71 self._load_public_key_bytes(), is_x509_cert=False) 72 bad_signature1 = b'' 73 self.assertFalse(verifier.verify(b'foo', bad_signature1)) 74 bad_signature2 = b'a' 75 self.assertFalse(verifier.verify(b'foo', bad_signature2)) 76 77 def test_from_string_pub_key(self): 78 public_key = self._load_public_key_bytes() 79 verifier = crypt.RsaVerifier.from_string( 80 public_key, is_x509_cert=False) 81 self.assertIsInstance(verifier, crypt.RsaVerifier) 82 self.assertIsInstance(verifier._pubkey, rsa.key.PublicKey) 83 84 def test_from_string_pub_key_unicode(self): 85 public_key = _helpers._from_bytes(self._load_public_key_bytes()) 86 verifier = crypt.RsaVerifier.from_string( 87 public_key, is_x509_cert=False) 88 self.assertIsInstance(verifier, crypt.RsaVerifier) 89 self.assertIsInstance(verifier._pubkey, rsa.key.PublicKey) 90 91 def test_from_string_pub_cert(self): 92 public_cert = self._load_public_cert_bytes() 93 verifier = crypt.RsaVerifier.from_string( 94 public_cert, is_x509_cert=True) 95 self.assertIsInstance(verifier, crypt.RsaVerifier) 96 self.assertIsInstance(verifier._pubkey, rsa.key.PublicKey) 97 98 def test_from_string_pub_cert_unicode(self): 99 public_cert = _helpers._from_bytes(self._load_public_cert_bytes()) 100 verifier = crypt.RsaVerifier.from_string( 101 public_cert, is_x509_cert=True) 102 self.assertIsInstance(verifier, crypt.RsaVerifier) 103 self.assertIsInstance(verifier._pubkey, rsa.key.PublicKey) 104 105 def test_from_string_pub_cert_failure(self): 106 cert_bytes = self._load_public_cert_bytes() 107 true_der = rsa.pem.load_pem(cert_bytes, 'CERTIFICATE') 108 with mock.patch('rsa.pem.load_pem', 109 return_value=true_der + b'extra') as load_pem: 110 with self.assertRaises(ValueError): 111 crypt.RsaVerifier.from_string(cert_bytes, is_x509_cert=True) 112 load_pem.assert_called_once_with(cert_bytes, 'CERTIFICATE') 113 114 115class TestRsaSigner(unittest2.TestCase): 116 117 PKCS1_KEY_FILENAME = os.path.join(os.path.dirname(__file__), 118 'data', 'privatekey.pem') 119 PKCS8_KEY_FILENAME = os.path.join(os.path.dirname(__file__), 120 'data', 'pem_from_pkcs12.pem') 121 PKCS12_KEY_FILENAME = os.path.join(os.path.dirname(__file__), 122 'data', 'privatekey.p12') 123 124 def _load_pkcs1_key_bytes(self): 125 with open(self.PKCS1_KEY_FILENAME, 'rb') as fh: 126 return fh.read() 127 128 def _load_pkcs8_key_bytes(self): 129 with open(self.PKCS8_KEY_FILENAME, 'rb') as fh: 130 return fh.read() 131 132 def _load_pkcs12_key_bytes(self): 133 with open(self.PKCS12_KEY_FILENAME, 'rb') as fh: 134 return fh.read() 135 136 def test_from_string_pkcs1(self): 137 key_bytes = self._load_pkcs1_key_bytes() 138 signer = crypt.RsaSigner.from_string(key_bytes) 139 self.assertIsInstance(signer, crypt.RsaSigner) 140 self.assertIsInstance(signer._key, rsa.key.PrivateKey) 141 142 def test_from_string_pkcs1_unicode(self): 143 key_bytes = _helpers._from_bytes(self._load_pkcs1_key_bytes()) 144 signer = crypt.RsaSigner.from_string(key_bytes) 145 self.assertIsInstance(signer, crypt.RsaSigner) 146 self.assertIsInstance(signer._key, rsa.key.PrivateKey) 147 148 def test_from_string_pkcs8(self): 149 key_bytes = self._load_pkcs8_key_bytes() 150 signer = crypt.RsaSigner.from_string(key_bytes) 151 self.assertIsInstance(signer, crypt.RsaSigner) 152 self.assertIsInstance(signer._key, rsa.key.PrivateKey) 153 154 def test_from_string_pkcs8_extra_bytes(self): 155 key_bytes = self._load_pkcs8_key_bytes() 156 _, pem_bytes = pem.readPemBlocksFromFile( 157 six.StringIO(_helpers._from_bytes(key_bytes)), 158 _pure_python_crypt._PKCS8_MARKER) 159 160 with mock.patch('pyasn1.codec.der.decoder.decode') as mock_decode: 161 key_info, remaining = None, 'extra' 162 mock_decode.return_value = (key_info, remaining) 163 with self.assertRaises(ValueError): 164 crypt.RsaSigner.from_string(key_bytes) 165 # Verify mock was called. 166 mock_decode.assert_called_once_with( 167 pem_bytes, asn1Spec=_pure_python_crypt._PKCS8_SPEC) 168 169 def test_from_string_pkcs8_unicode(self): 170 key_bytes = _helpers._from_bytes(self._load_pkcs8_key_bytes()) 171 signer = crypt.RsaSigner.from_string(key_bytes) 172 self.assertIsInstance(signer, crypt.RsaSigner) 173 self.assertIsInstance(signer._key, rsa.key.PrivateKey) 174 175 def test_from_string_pkcs12(self): 176 key_bytes = self._load_pkcs12_key_bytes() 177 with self.assertRaises(ValueError): 178 crypt.RsaSigner.from_string(key_bytes) 179 180 def test_from_string_bogus_key(self): 181 key_bytes = 'bogus-key' 182 with self.assertRaises(ValueError): 183 crypt.RsaSigner.from_string(key_bytes) 184