1# Copyright 2016 Google Inc. 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 base64 16import json 17import os 18 19from cryptography.hazmat.primitives.asymmetric import ec 20import pytest 21 22from google.auth import _helpers 23from google.auth.crypt import base 24from google.auth.crypt import es256 25 26 27DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "data") 28 29# To generate es256_privatekey.pem, es256_privatekey.pub, and 30# es256_public_cert.pem: 31# $ openssl ecparam -genkey -name prime256v1 -noout -out es256_privatekey.pem 32# $ openssl ec -in es256-private-key.pem -pubout -out es256-publickey.pem 33# $ openssl req -new -x509 -key es256_privatekey.pem -out \ 34# > es256_public_cert.pem 35 36with open(os.path.join(DATA_DIR, "es256_privatekey.pem"), "rb") as fh: 37 PRIVATE_KEY_BYTES = fh.read() 38 PKCS1_KEY_BYTES = PRIVATE_KEY_BYTES 39 40with open(os.path.join(DATA_DIR, "es256_publickey.pem"), "rb") as fh: 41 PUBLIC_KEY_BYTES = fh.read() 42 43with open(os.path.join(DATA_DIR, "es256_public_cert.pem"), "rb") as fh: 44 PUBLIC_CERT_BYTES = fh.read() 45 46SERVICE_ACCOUNT_JSON_FILE = os.path.join(DATA_DIR, "es256_service_account.json") 47 48with open(SERVICE_ACCOUNT_JSON_FILE, "r") as fh: 49 SERVICE_ACCOUNT_INFO = json.load(fh) 50 51 52class TestES256Verifier(object): 53 def test_verify_success(self): 54 to_sign = b"foo" 55 signer = es256.ES256Signer.from_string(PRIVATE_KEY_BYTES) 56 actual_signature = signer.sign(to_sign) 57 58 verifier = es256.ES256Verifier.from_string(PUBLIC_KEY_BYTES) 59 assert verifier.verify(to_sign, actual_signature) 60 61 def test_verify_unicode_success(self): 62 to_sign = u"foo" 63 signer = es256.ES256Signer.from_string(PRIVATE_KEY_BYTES) 64 actual_signature = signer.sign(to_sign) 65 66 verifier = es256.ES256Verifier.from_string(PUBLIC_KEY_BYTES) 67 assert verifier.verify(to_sign, actual_signature) 68 69 def test_verify_failure(self): 70 verifier = es256.ES256Verifier.from_string(PUBLIC_KEY_BYTES) 71 bad_signature1 = b"" 72 assert not verifier.verify(b"foo", bad_signature1) 73 bad_signature2 = b"a" 74 assert not verifier.verify(b"foo", bad_signature2) 75 76 def test_verify_failure_with_wrong_raw_signature(self): 77 to_sign = b"foo" 78 79 # This signature has a wrong "r" value in the "(r,s)" raw signature. 80 wrong_signature = base64.urlsafe_b64decode( 81 b"m7oaRxUDeYqjZ8qiMwo0PZLTMZWKJLFQREpqce1StMIa_yXQQ-C5WgeIRHW7OqlYSDL0XbUrj_uAw9i-QhfOJQ==" 82 ) 83 84 verifier = es256.ES256Verifier.from_string(PUBLIC_KEY_BYTES) 85 assert not verifier.verify(to_sign, wrong_signature) 86 87 def test_from_string_pub_key(self): 88 verifier = es256.ES256Verifier.from_string(PUBLIC_KEY_BYTES) 89 assert isinstance(verifier, es256.ES256Verifier) 90 assert isinstance(verifier._pubkey, ec.EllipticCurvePublicKey) 91 92 def test_from_string_pub_key_unicode(self): 93 public_key = _helpers.from_bytes(PUBLIC_KEY_BYTES) 94 verifier = es256.ES256Verifier.from_string(public_key) 95 assert isinstance(verifier, es256.ES256Verifier) 96 assert isinstance(verifier._pubkey, ec.EllipticCurvePublicKey) 97 98 def test_from_string_pub_cert(self): 99 verifier = es256.ES256Verifier.from_string(PUBLIC_CERT_BYTES) 100 assert isinstance(verifier, es256.ES256Verifier) 101 assert isinstance(verifier._pubkey, ec.EllipticCurvePublicKey) 102 103 def test_from_string_pub_cert_unicode(self): 104 public_cert = _helpers.from_bytes(PUBLIC_CERT_BYTES) 105 verifier = es256.ES256Verifier.from_string(public_cert) 106 assert isinstance(verifier, es256.ES256Verifier) 107 assert isinstance(verifier._pubkey, ec.EllipticCurvePublicKey) 108 109 110class TestES256Signer(object): 111 def test_from_string_pkcs1(self): 112 signer = es256.ES256Signer.from_string(PKCS1_KEY_BYTES) 113 assert isinstance(signer, es256.ES256Signer) 114 assert isinstance(signer._key, ec.EllipticCurvePrivateKey) 115 116 def test_from_string_pkcs1_unicode(self): 117 key_bytes = _helpers.from_bytes(PKCS1_KEY_BYTES) 118 signer = es256.ES256Signer.from_string(key_bytes) 119 assert isinstance(signer, es256.ES256Signer) 120 assert isinstance(signer._key, ec.EllipticCurvePrivateKey) 121 122 def test_from_string_bogus_key(self): 123 key_bytes = "bogus-key" 124 with pytest.raises(ValueError): 125 es256.ES256Signer.from_string(key_bytes) 126 127 def test_from_service_account_info(self): 128 signer = es256.ES256Signer.from_service_account_info(SERVICE_ACCOUNT_INFO) 129 130 assert signer.key_id == SERVICE_ACCOUNT_INFO[base._JSON_FILE_PRIVATE_KEY_ID] 131 assert isinstance(signer._key, ec.EllipticCurvePrivateKey) 132 133 def test_from_service_account_info_missing_key(self): 134 with pytest.raises(ValueError) as excinfo: 135 es256.ES256Signer.from_service_account_info({}) 136 137 assert excinfo.match(base._JSON_FILE_PRIVATE_KEY) 138 139 def test_from_service_account_file(self): 140 signer = es256.ES256Signer.from_service_account_file(SERVICE_ACCOUNT_JSON_FILE) 141 142 assert signer.key_id == SERVICE_ACCOUNT_INFO[base._JSON_FILE_PRIVATE_KEY_ID] 143 assert isinstance(signer._key, ec.EllipticCurvePrivateKey) 144