1# Copyright 2016 Google LLC 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 15import json 16import os 17 18from cryptography.hazmat.primitives.asymmetric import rsa 19import pytest 20 21from google.auth import _helpers 22from google.auth.crypt import _cryptography_rsa 23from google.auth.crypt import base 24 25 26DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "data") 27 28# To generate privatekey.pem, privatekey.pub, and public_cert.pem: 29# $ openssl req -new -newkey rsa:1024 -x509 -nodes -out public_cert.pem \ 30# > -keyout privatekey.pem 31# $ openssl rsa -in privatekey.pem -pubout -out privatekey.pub 32 33with open(os.path.join(DATA_DIR, "privatekey.pem"), "rb") as fh: 34 PRIVATE_KEY_BYTES = fh.read() 35 PKCS1_KEY_BYTES = PRIVATE_KEY_BYTES 36 37with open(os.path.join(DATA_DIR, "privatekey.pub"), "rb") as fh: 38 PUBLIC_KEY_BYTES = fh.read() 39 40with open(os.path.join(DATA_DIR, "public_cert.pem"), "rb") as fh: 41 PUBLIC_CERT_BYTES = fh.read() 42 43# To generate pem_from_pkcs12.pem and privatekey.p12: 44# $ openssl pkcs12 -export -out privatekey.p12 -inkey privatekey.pem \ 45# > -in public_cert.pem 46# $ openssl pkcs12 -in privatekey.p12 -nocerts -nodes \ 47# > -out pem_from_pkcs12.pem 48 49with open(os.path.join(DATA_DIR, "pem_from_pkcs12.pem"), "rb") as fh: 50 PKCS8_KEY_BYTES = fh.read() 51 52with open(os.path.join(DATA_DIR, "privatekey.p12"), "rb") as fh: 53 PKCS12_KEY_BYTES = fh.read() 54 55# The service account JSON file can be generated from the Google Cloud Console. 56SERVICE_ACCOUNT_JSON_FILE = os.path.join(DATA_DIR, "service_account.json") 57 58with open(SERVICE_ACCOUNT_JSON_FILE, "r") as fh: 59 SERVICE_ACCOUNT_INFO = json.load(fh) 60 61 62class TestRSAVerifier(object): 63 def test_verify_success(self): 64 to_sign = b"foo" 65 signer = _cryptography_rsa.RSASigner.from_string(PRIVATE_KEY_BYTES) 66 actual_signature = signer.sign(to_sign) 67 68 verifier = _cryptography_rsa.RSAVerifier.from_string(PUBLIC_KEY_BYTES) 69 assert verifier.verify(to_sign, actual_signature) 70 71 def test_verify_unicode_success(self): 72 to_sign = u"foo" 73 signer = _cryptography_rsa.RSASigner.from_string(PRIVATE_KEY_BYTES) 74 actual_signature = signer.sign(to_sign) 75 76 verifier = _cryptography_rsa.RSAVerifier.from_string(PUBLIC_KEY_BYTES) 77 assert verifier.verify(to_sign, actual_signature) 78 79 def test_verify_failure(self): 80 verifier = _cryptography_rsa.RSAVerifier.from_string(PUBLIC_KEY_BYTES) 81 bad_signature1 = b"" 82 assert not verifier.verify(b"foo", bad_signature1) 83 bad_signature2 = b"a" 84 assert not verifier.verify(b"foo", bad_signature2) 85 86 def test_from_string_pub_key(self): 87 verifier = _cryptography_rsa.RSAVerifier.from_string(PUBLIC_KEY_BYTES) 88 assert isinstance(verifier, _cryptography_rsa.RSAVerifier) 89 assert isinstance(verifier._pubkey, rsa.RSAPublicKey) 90 91 def test_from_string_pub_key_unicode(self): 92 public_key = _helpers.from_bytes(PUBLIC_KEY_BYTES) 93 verifier = _cryptography_rsa.RSAVerifier.from_string(public_key) 94 assert isinstance(verifier, _cryptography_rsa.RSAVerifier) 95 assert isinstance(verifier._pubkey, rsa.RSAPublicKey) 96 97 def test_from_string_pub_cert(self): 98 verifier = _cryptography_rsa.RSAVerifier.from_string(PUBLIC_CERT_BYTES) 99 assert isinstance(verifier, _cryptography_rsa.RSAVerifier) 100 assert isinstance(verifier._pubkey, rsa.RSAPublicKey) 101 102 def test_from_string_pub_cert_unicode(self): 103 public_cert = _helpers.from_bytes(PUBLIC_CERT_BYTES) 104 verifier = _cryptography_rsa.RSAVerifier.from_string(public_cert) 105 assert isinstance(verifier, _cryptography_rsa.RSAVerifier) 106 assert isinstance(verifier._pubkey, rsa.RSAPublicKey) 107 108 109class TestRSASigner(object): 110 def test_from_string_pkcs1(self): 111 signer = _cryptography_rsa.RSASigner.from_string(PKCS1_KEY_BYTES) 112 assert isinstance(signer, _cryptography_rsa.RSASigner) 113 assert isinstance(signer._key, rsa.RSAPrivateKey) 114 115 def test_from_string_pkcs1_unicode(self): 116 key_bytes = _helpers.from_bytes(PKCS1_KEY_BYTES) 117 signer = _cryptography_rsa.RSASigner.from_string(key_bytes) 118 assert isinstance(signer, _cryptography_rsa.RSASigner) 119 assert isinstance(signer._key, rsa.RSAPrivateKey) 120 121 def test_from_string_pkcs8(self): 122 signer = _cryptography_rsa.RSASigner.from_string(PKCS8_KEY_BYTES) 123 assert isinstance(signer, _cryptography_rsa.RSASigner) 124 assert isinstance(signer._key, rsa.RSAPrivateKey) 125 126 def test_from_string_pkcs8_unicode(self): 127 key_bytes = _helpers.from_bytes(PKCS8_KEY_BYTES) 128 signer = _cryptography_rsa.RSASigner.from_string(key_bytes) 129 assert isinstance(signer, _cryptography_rsa.RSASigner) 130 assert isinstance(signer._key, rsa.RSAPrivateKey) 131 132 def test_from_string_pkcs12(self): 133 with pytest.raises(ValueError): 134 _cryptography_rsa.RSASigner.from_string(PKCS12_KEY_BYTES) 135 136 def test_from_string_bogus_key(self): 137 key_bytes = "bogus-key" 138 with pytest.raises(ValueError): 139 _cryptography_rsa.RSASigner.from_string(key_bytes) 140 141 def test_from_service_account_info(self): 142 signer = _cryptography_rsa.RSASigner.from_service_account_info( 143 SERVICE_ACCOUNT_INFO 144 ) 145 146 assert signer.key_id == SERVICE_ACCOUNT_INFO[base._JSON_FILE_PRIVATE_KEY_ID] 147 assert isinstance(signer._key, rsa.RSAPrivateKey) 148 149 def test_from_service_account_info_missing_key(self): 150 with pytest.raises(ValueError) as excinfo: 151 _cryptography_rsa.RSASigner.from_service_account_info({}) 152 153 assert excinfo.match(base._JSON_FILE_PRIVATE_KEY) 154 155 def test_from_service_account_file(self): 156 signer = _cryptography_rsa.RSASigner.from_service_account_file( 157 SERVICE_ACCOUNT_JSON_FILE 158 ) 159 160 assert signer.key_id == SERVICE_ACCOUNT_INFO[base._JSON_FILE_PRIVATE_KEY_ID] 161 assert isinstance(signer._key, rsa.RSAPrivateKey) 162