def test_jwt_public_key_sign_verify(self, lang): private_keyset = testing_servers.new_keyset(lang, jwt.jwt_es256_template()) public_keyset = testing_servers.public_keyset(lang, private_keyset) signer = testing_servers.jwt_public_key_sign(lang, private_keyset) verifier = testing_servers.jwt_public_key_verify(lang, public_keyset) now = datetime.datetime.now(tz=datetime.timezone.utc) token = jwt.new_raw_jwt( issuer='issuer', subject='subject', audiences=['audience1', 'audience2'], jwt_id='jwt_id', expiration=now + datetime.timedelta(seconds=10), custom_claims={'switch': True, 'pi': 3.14159}) compact = signer.sign_and_encode(token) validator = jwt.new_validator( expected_issuer='issuer', expected_audience='audience1', fixed_now=now) verified_jwt = verifier.verify_and_decode(compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer') self.assertEqual(verified_jwt.subject(), 'subject') self.assertEqual(verified_jwt.jwt_id(), 'jwt_id') self.assertEqual(verified_jwt.custom_claim('switch'), True) self.assertEqual(verified_jwt.custom_claim('pi'), 3.14159) validator2 = jwt.new_validator( expected_audience='wrong_audience', fixed_now=now) with self.assertRaises(tink.TinkError): verifier.verify_and_decode(compact, validator2)
def test_jwt_signature_without_primary(self, key_template_name, lang): """Unsets the primary key and tries to sign and verify JWT signatures.""" template = supported_key_types.KEY_TEMPLATE[key_template_name] private_keyset = testing_servers.new_keyset(lang, template) public_keyset = testing_servers.public_keyset(lang, private_keyset) signer = testing_servers.jwt_public_key_sign(lang, private_keyset) now = datetime.datetime.now(tz=datetime.timezone.utc) raw_jwt = jwt.new_raw_jwt(issuer='issuer', expiration=now + datetime.timedelta(seconds=100)) token = signer.sign_and_encode(raw_jwt) signer_without_primary = testing_servers.jwt_public_key_sign( lang, unset_primary(private_keyset)) with self.assertRaises(tink.TinkError): signer_without_primary.sign_and_encode(raw_jwt) verifier_without_primary = testing_servers.jwt_public_key_verify( lang, unset_primary(public_keyset)) validator = jwt.new_validator(expected_issuer='issuer', fixed_now=now) if lang in ['cc', 'java', 'python']: # C++, Java and Python currently allow this. verifier_without_primary.verify_and_decode(token, validator) else: with self.assertRaises(tink.TinkError): verifier_without_primary.verify_and_decode(token, validator)
def test_jwt_public_key_sign_verify(self, lang): key_format = jwt_ecdsa_pb2.JwtEcdsaKeyFormat( algorithm=jwt_ecdsa_pb2.ES256) key_template = tink_pb2.KeyTemplate( type_url='type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey', value=key_format.SerializeToString(), output_prefix_type=tink_pb2.RAW) private_keyset = testing_servers.new_keyset(lang, key_template) public_keyset = testing_servers.public_keyset(lang, private_keyset) signer = testing_servers.jwt_public_key_sign(lang, private_keyset) verifier = testing_servers.jwt_public_key_verify(lang, public_keyset) now = datetime.datetime.now(tz=datetime.timezone.utc) token = jwt.new_raw_jwt( issuer='issuer', subject='subject', audiences=['audience1', 'audience2'], jwt_id='jwt_id', expiration=now + datetime.timedelta(seconds=10), custom_claims={'switch': True, 'pi': 3.14159}) compact = signer.sign_and_encode(token) validator = jwt.new_validator(audience='audience1', fixed_now=now) verified_jwt = verifier.verify_and_decode(compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer') self.assertEqual(verified_jwt.subject(), 'subject') self.assertEqual(verified_jwt.jwt_id(), 'jwt_id') self.assertEqual(verified_jwt.custom_claim('switch'), True) self.assertEqual(verified_jwt.custom_claim('pi'), 3.14159) validator2 = jwt.new_validator(audience='wrong_audience', fixed_now=now) with self.assertRaises(tink.TinkError): verifier.verify_and_decode(compact, validator2)
def test_encrypt_decrypt(self, key_template_name, supported_langs): key_template = supported_key_types.KEY_TEMPLATE[key_template_name] private_keyset = testing_servers.new_keyset('java', key_template) supported_signers = [ testing_servers.public_key_sign(lang, private_keyset) for lang in supported_langs ] unsupported_signers = [ testing_servers.public_key_sign(lang, private_keyset) for lang in SUPPORTED_LANGUAGES if lang not in supported_langs ] public_keyset = testing_servers.public_keyset('java', private_keyset) supported_verifiers = [ testing_servers.public_key_verify(lang, public_keyset) for lang in supported_langs ] unsupported_verifiers = [ testing_servers.public_key_verify(lang, public_keyset) for lang in testing_servers.LANGUAGES if lang not in supported_langs ] for signer in supported_signers: message = ( b'A message to be signed using key_template %s in %s.' % (key_template_name.encode('utf8'), signer.lang.encode('utf8'))) sign = signer.sign(message) for verifier in supported_verifiers: self.assertIsNone(verifier.verify(sign, message)) for verifier in unsupported_verifiers: with self.assertRaises(tink.TinkError): verifier.verify(sign, message) for signer in unsupported_signers: with self.assertRaises(tink.TinkError): _ = signer.sign(message)
def test_encrypt_decrypt(self, key_template_name): if key_template_name in _ADDITIONAL_KEY_TEMPLATES: key_template, supported_langs = _ADDITIONAL_KEY_TEMPLATES[ key_template_name] else: key_template = supported_key_types.KEY_TEMPLATE[key_template_name] supported_langs = ( supported_key_types. SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME[key_template_name]) self.assertNotEmpty(supported_langs) # Take the first supported language to generate the private keyset. private_keyset = testing_servers.new_keyset(supported_langs[0], key_template) supported_decs = [ testing_servers.hybrid_decrypt(lang, private_keyset) for lang in supported_langs ] unsupported_decs = [ testing_servers.hybrid_decrypt(lang, private_keyset) for lang in SUPPORTED_LANGUAGES if lang not in supported_langs ] public_keyset = testing_servers.public_keyset(supported_langs[0], private_keyset) supported_encs = [ testing_servers.hybrid_encrypt(lang, public_keyset) for lang in supported_langs ] unsupported_encs = [ testing_servers.hybrid_encrypt(lang, public_keyset) for lang in testing_servers.LANGUAGES if lang not in supported_langs ] for enc in supported_encs: plaintext = ( b'This is some plaintext message to be encrypted using key_template ' b'%s in %s.' % (key_template_name.encode('utf8'), enc.lang.encode('utf8'))) context_info = ( b'Some context info for %s using %s for encryption.' % (key_template_name.encode('utf8'), enc.lang.encode('utf8'))) ciphertext = enc.encrypt(plaintext, context_info) for dec in supported_decs: output = dec.decrypt(ciphertext, context_info) self.assertEqual(output, plaintext) for dec in unsupported_decs: with self.assertRaises( tink.TinkError, msg= 'Language %s supports hybrid decrypt with %s unexpectedly' % (dec.lang, key_template_name)): dec.decrypt(ciphertext, context_info) for enc in unsupported_encs: with self.assertRaises( tink.TinkError, msg= 'Language %s supports hybrid encrypt with %s unexpectedly' % (enc.lang, key_template_name)): enc.encrypt(b'plaintext', b'context_info')
def test_signature(self, lang): private_handle = testing_servers.new_keyset( lang, signature.signature_key_templates.ED25519) public_handle = testing_servers.public_keyset(lang, private_handle) sign_primitive = testing_servers.public_key_sign(lang, private_handle) data = b'The quick brown fox jumps over the lazy dog' signature_value = sign_primitive.sign(data) verify_primitive = testing_servers.public_key_verify(lang, public_handle) verify_primitive.verify(signature_value, data) with self.assertRaises(tink.TinkError): verify_primitive.verify(b'foo', data)
def test_jwt_public_key_sign_verify(self, key_template_name): supported_langs = supported_key_types.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME[ key_template_name] self.assertNotEmpty(supported_langs) key_template = supported_key_types.KEY_TEMPLATE[key_template_name] # Take the first supported language to generate the private keyset. private_keyset = testing_servers.new_keyset(supported_langs[0], key_template) supported_signers = [ testing_servers.jwt_public_key_sign(lang, private_keyset) for lang in supported_langs ] unsupported_signers = [ testing_servers.jwt_public_key_sign(lang, private_keyset) for lang in SUPPORTED_LANGUAGES if lang not in supported_langs ] public_keyset = testing_servers.public_keyset('java', private_keyset) supported_verifiers = [ testing_servers.jwt_public_key_verify(lang, public_keyset) for lang in supported_langs ] unsupported_verifiers = [ testing_servers.jwt_public_key_verify(lang, public_keyset) for lang in SUPPORTED_LANGUAGES if lang not in supported_langs ] now = datetime.datetime.now(tz=datetime.timezone.utc) raw_jwt = jwt.new_raw_jwt( issuer='issuer', audiences=['audience1', 'audience2'], expiration=now + datetime.timedelta(seconds=100)) for signer in supported_signers: compact = signer.sign_and_encode(raw_jwt) validator = jwt.new_validator(audience='audience1', fixed_now=now) for verifier in supported_verifiers: verified_jwt = verifier.verify_and_decode(compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer') for verifier in unsupported_verifiers: with self.assertRaises( tink.TinkError, msg='%s supports jwt_public_key_verify with %s unexpectedly' % (verifier.lang, key_template_name)): verifier.verify_and_decode(compact, validator) for signer in unsupported_signers: with self.assertRaises( tink.TinkError, msg='%s supports jwt_public_key_sign with %s unexpectedly' % (signer.lang, key_template_name)): _ = signer.sign_and_encode(raw_jwt)
def test_hybrid(self, lang): private_handle = testing_servers.new_keyset( lang, hybrid.hybrid_key_templates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM) public_handle = testing_servers.public_keyset(lang, private_handle) enc_primitive = testing_servers.hybrid_encrypt(lang, public_handle) data = b'The quick brown fox jumps over the lazy dog' context_info = b'context' ciphertext = enc_primitive.encrypt(data, context_info) dec_primitive = testing_servers.hybrid_decrypt(lang, private_handle) output = dec_primitive.decrypt(ciphertext, context_info) self.assertEqual(output, data) with self.assertRaises(tink.TinkError): dec_primitive.decrypt(b'foo', context_info)
def test_sign_verify(self, key_template_name): supported_langs = supported_key_types.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME[ key_template_name] self.assertNotEmpty(supported_langs) key_template = supported_key_types.KEY_TEMPLATE[key_template_name] # Take the first supported language to generate the private keyset. private_keyset = testing_servers.new_keyset(supported_langs[0], key_template) supported_signers = [ testing_servers.public_key_sign(lang, private_keyset) for lang in supported_langs ] unsupported_signers = [ testing_servers.public_key_sign(lang, private_keyset) for lang in SUPPORTED_LANGUAGES if lang not in supported_langs ] public_keyset = testing_servers.public_keyset('java', private_keyset) supported_verifiers = [ testing_servers.public_key_verify(lang, public_keyset) for lang in supported_langs ] unsupported_verifiers = [ testing_servers.public_key_verify(lang, public_keyset) for lang in testing_servers.LANGUAGES if lang not in supported_langs ] for signer in supported_signers: message = ( b'A message to be signed using key_template %s in %s.' % (key_template_name.encode('utf8'), signer.lang.encode('utf8'))) sign = signer.sign(message) for verifier in supported_verifiers: self.assertIsNone(verifier.verify(sign, message)) for verifier in unsupported_verifiers: with self.assertRaises( tink.TinkError, msg= 'Language %s supports signature verify with %s unexpectedly' % (verifier.lang, key_template_name)): verifier.verify(sign, message) for signer in unsupported_signers: with self.assertRaises( tink.TinkError, msg= 'Language %s supports signature sign with %s unexpectedly' % (signer.lang, key_template_name)): _ = signer.sign(message)
def test_hybrid_without_primary(self, key_template_name, lang): """Unsets the primary key and tries to use hybrid encryption.""" template = supported_key_types.KEY_TEMPLATE[key_template_name] private_keyset = testing_servers.new_keyset(lang, template) public_keyset = testing_servers.public_keyset(lang, private_keyset) ciphertext = testing_servers.hybrid_encrypt( lang, public_keyset).encrypt(b'foo', b'context_info') dec_without_primary = testing_servers.hybrid_decrypt( lang, unset_primary(private_keyset)) with self.assertRaises(tink.TinkError): dec_without_primary.decrypt(ciphertext, b'context_info') enc_without_primary = testing_servers.hybrid_encrypt( lang, unset_primary(public_keyset)) with self.assertRaises(tink.TinkError): enc_without_primary.encrypt(b'foo', b'context_info')
def test_encrypt_decrypt(self, key_template_name, supported_langs): self.assertNotEmpty(supported_langs) key_template = supported_key_types.KEY_TEMPLATE[key_template_name] # Take the first supported language to generate the private keyset. private_keyset = testing_servers.new_keyset(supported_langs[0], key_template) supported_decs = [ testing_servers.hybrid_decrypt(lang, private_keyset) for lang in supported_langs ] unsupported_decs = [ testing_servers.hybrid_decrypt(lang, private_keyset) for lang in SUPPORTED_LANGUAGES if lang not in supported_langs ] public_keyset = testing_servers.public_keyset('java', private_keyset) supported_encs = [ testing_servers.hybrid_encrypt(lang, public_keyset) for lang in supported_langs ] unsupported_encs = [ testing_servers.hybrid_encrypt(lang, public_keyset) for lang in testing_servers.LANGUAGES if lang not in supported_langs ] for enc in supported_encs: plaintext = ( b'This is some plaintext message to be encrypted using key_template ' b'%s in %s.' % (key_template_name.encode('utf8'), enc.lang.encode('utf8'))) context_info = ( b'Some context info for %s using %s for encryption.' % (key_template_name.encode('utf8'), enc.lang.encode('utf8'))) ciphertext = enc.encrypt(plaintext, context_info) for dec in supported_decs: output = dec.decrypt(ciphertext, context_info) self.assertEqual(output, plaintext) for dec in unsupported_decs: with self.assertRaises(tink.TinkError): dec.decrypt(ciphertext, context_info) for enc in unsupported_encs: with self.assertRaises(tink.TinkError): enc.encrypt(b'plaintext', b'context_info')
def test_jwt_public_key_sign_export_import_verify(self, lang): private_keyset = testing_servers.new_keyset(lang, jwt.jwt_es256_template()) public_keyset = testing_servers.public_keyset(lang, private_keyset) # sign and export public key signer = testing_servers.jwt_public_key_sign(lang, private_keyset) now = datetime.datetime.now(tz=datetime.timezone.utc) token = jwt.new_raw_jwt( jwt_id='jwt_id', expiration=now + datetime.timedelta(seconds=100)) compact = signer.sign_and_encode(token) public_jwk_set = testing_servers.jwk_set_from_keyset(lang, public_keyset) # verify using public_jwk_set imported_public_keyset = testing_servers.jwk_set_to_keyset( lang, public_jwk_set) verifier = testing_servers.jwt_public_key_verify(lang, imported_public_keyset) validator = jwt.new_validator(fixed_now=now) verified_jwt = verifier.verify_and_decode(compact, validator) self.assertEqual(verified_jwt.jwt_id(), 'jwt_id')
def test_signature_without_primary(self, key_template_name, lang): """Unsets the primary key and tries to sign and verify signatures.""" template = supported_key_types.KEY_TEMPLATE[key_template_name] private_keyset = testing_servers.new_keyset(lang, template) public_keyset = testing_servers.public_keyset(lang, private_keyset) sig = testing_servers.public_key_sign(lang, private_keyset).sign(b'foo') testing_servers.public_key_verify(lang, public_keyset).verify(sig, b'foo') signer_without_primary = testing_servers.public_key_sign( lang, unset_primary(private_keyset)) verifier_without_primary = testing_servers.public_key_verify( lang, unset_primary(public_keyset)) with self.assertRaises(tink.TinkError): signer_without_primary.sign(b'foo') if lang in ['java', 'python']: # Java and Python currently allow this. verifier_without_primary.verify(sig, b'foo') else: with self.assertRaises(tink.TinkError): verifier_without_primary.verify(sig, b'foo')
def test_jwt_public_key_sign_export_import_verify(self, key_template_name): supported_langs = supported_key_types.SUPPORTED_LANGUAGES_BY_TEMPLATE_NAME[ key_template_name] self.assertNotEmpty(supported_langs) key_template = supported_key_types.KEY_TEMPLATE[key_template_name] # Take the first supported language to generate the private keyset. private_keyset = testing_servers.new_keyset(supported_langs[0], key_template) now = datetime.datetime.now(tz=datetime.timezone.utc) raw_jwt = jwt.new_raw_jwt(issuer='issuer', expiration=now + datetime.timedelta(seconds=100)) validator = jwt.new_validator(expected_issuer='issuer', fixed_now=now) for lang1 in supported_langs: # in lang1: sign token and export public keyset to a JWK set signer = testing_servers.jwt_public_key_sign(lang1, private_keyset) compact = signer.sign_and_encode(raw_jwt) public_keyset = testing_servers.public_keyset( lang1, private_keyset) public_jwk_set = testing_servers.jwk_set_from_keyset( lang1, public_keyset) for lang2 in supported_langs: # in lang2: import the public JWK set and verify the token public_keyset = testing_servers.jwk_set_to_keyset( lang2, public_jwk_set) verifier = testing_servers.jwt_public_key_verify( lang2, public_keyset) verified_jwt = verifier.verify_and_decode(compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer') # Additional tests for the "kid" property of the JWK and the "kid" # header of the token. Either of them may be missing, but they must not # have different values. jwks = json.loads(public_jwk_set) has_kid = 'kid' in jwks['keys'][0] if has_kid: # Change the "kid" property of the JWK. jwks['keys'][0]['kid'] = 'unknown kid' public_keyset = testing_servers.jwk_set_to_keyset( lang2, json.dumps(jwks)) verifier = testing_servers.jwt_public_key_verify( lang2, public_keyset) with self.assertRaises( tink.TinkError, msg= '%s accepts tokens with an incorrect kid unexpectedly' % lang2): verifier.verify_and_decode(compact, validator) # Remove the "kid" property of the JWK. del jwks['keys'][0]['kid'] public_keyset = testing_servers.jwk_set_to_keyset( lang2, json.dumps(jwks)) verifier = testing_servers.jwt_public_key_verify( lang2, public_keyset) verified_jwt = verifier.verify_and_decode( compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer') else: # Add a "kid" property of the JWK. jwks['keys'][0]['kid'] = 'unknown kid' public_keyset = testing_servers.jwk_set_to_keyset( lang2, json.dumps(jwks)) verifier = testing_servers.jwt_public_key_verify( lang2, public_keyset) verified_jwt = verifier.verify_and_decode( compact, validator) self.assertEqual(verified_jwt.issuer(), 'issuer')