def test_keyset_info(self): keyset = tink_pb2.Keyset(primary_key_id=2) keyset.key.extend([ helper.fake_key(value=b'v1', type_url='t1', key_id=1, status=tink_pb2.ENABLED, output_prefix_type=tink_pb2.TINK), helper.fake_key(value=b'v2', type_url='t2', key_id=2, status=tink_pb2.DESTROYED, output_prefix_type=tink_pb2.RAW) ]) handle = core.KeysetHandle(keyset) expected_keyset_info = tink_pb2.KeysetInfo(primary_key_id=2) info1 = expected_keyset_info.key_info.add() info1.type_url = 't1' info1.status = tink_pb2.ENABLED info1.output_prefix_type = tink_pb2.TINK info1.key_id = 1 info2 = expected_keyset_info.key_info.add() info2.type_url = 't2' info2.status = tink_pb2.DESTROYED info2.output_prefix_type = tink_pb2.RAW info2.key_id = 2 self.assertEqual(expected_keyset_info, handle.keyset_info())
def _keyset_proto(keyset: bytes) -> tink_pb2.Keyset: keyset_proto = tink_pb2.Keyset() keyset_proto.ParseFromString(keyset) # We sort the keys, since we want keysets to be considered equal even if the # keys are in different order. keyset_proto.key.sort(key=lambda k: k.key_id) return keyset_proto
def test_primitive_fails_on_empty_keyset(self): keyset = tink_pb2.Keyset() keyset.key.extend([helper.fake_key(key_id=1, status=tink_pb2.DESTROYED)]) keyset.primary_key_id = 1 handle = _keyset_handle(keyset) with self.assertRaisesRegex(core.TinkError, 'empty keyset'): handle.primitive(aead.Aead)
def test_init_fails_on_key_with_unknown_status(self): keyset = tink_pb2.Keyset() keyset.key.extend( [helper.fake_key(key_id=123, status=tink_pb2.UNKNOWN_STATUS)]) keyset.primary_key_id = 123 with self.assertRaises(core.TinkError): _ = _keyset_handle(keyset)
def test_primitive_fails_on_key_with_unknown_status(self): keyset = tink_pb2.Keyset() keyset.key.extend( [helper.fake_key(key_id=1234, status=tink_pb2.UNKNOWN_STATUS)]) keyset.primary_key_id = 1234 handle = _keyset_handle(keyset) with self.assertRaisesRegex(core.TinkError, 'key 1234 has unknown status'): handle.primitive(aead.Aead)
def from_keyset_handle(keyset_handle: tink.KeysetHandle) -> KeysetBuilder: """Return a KeysetBuilder for a Keyset copied from a KeysetHandle.""" keyset_buffer = io.BytesIO() cleartext_keyset_handle.write( tink.BinaryKeysetWriter(keyset_buffer), keyset_handle) keyset = tink_pb2.Keyset() keyset.ParseFromString(keyset_buffer.getvalue()) return KeysetBuilder(keyset)
def test_init_fails_on_multiple_primary_keys(self): keyset = tink_pb2.Keyset() keyset.key.extend( [helper.fake_key(key_id=123), helper.fake_key(key_id=123)]) keyset.primary_key_id = 123 with self.assertRaises(core.TinkError): _ = _keyset_handle(keyset)
def test_init_fails_on_key_with_unknown_prefix(self): keyset = tink_pb2.Keyset() keyset.key.extend([ helper.fake_key(key_id=123, output_prefix_type=tink_pb2.UNKNOWN_PREFIX) ]) keyset.primary_key_id = 123 with self.assertRaises(core.TinkError): _ = _keyset_handle(keyset)
def test_primitive_fails_on_key_without_keydata(self): keyset = tink_pb2.Keyset() key = helper.fake_key(key_id=123) key.ClearField('key_data') keyset.key.extend([key]) keyset.primary_key_id = 123 handle = core.KeysetHandle(keyset) with self.assertRaisesRegex(core.TinkError, 'key 123 has no key data'): handle.primitive(aead.Aead)
def test_primitive_fails_on_key_with_unknown_prefix(self): keyset = tink_pb2.Keyset() keyset.key.extend([ helper.fake_key(key_id=12, output_prefix_type=tink_pb2.UNKNOWN_PREFIX) ]) keyset.primary_key_id = 12 handle = _keyset_handle(keyset) with self.assertRaisesRegex(core.TinkError, 'key 12 has unknown prefix'): handle.primitive(aead.Aead)
def test_init_fails_on_multiple_primary_keys(self): keyset = tink_pb2.Keyset() keyset.key.extend( [helper.fake_key(key_id=12345), helper.fake_key(key_id=12345)]) keyset.primary_key_id = 12345 with self.assertRaisesRegex(core.TinkError, 'keyset contains multiple primary keys'): _ = _keyset_handle(keyset)
def read(self) -> tink_pb2.Keyset: if not self._serialized_keyset: raise core.TinkError('No keyset found') try: keyset = tink_pb2.Keyset() keyset.ParseFromString(self._serialized_keyset) return keyset except message.DecodeError as e: raise core.TinkError(e)
def test_init_fails_on_key_without_keydata(self): keyset = tink_pb2.Keyset() key = helper.fake_key(key_id=123) key.ClearField('key_data') keyset.key.extend([key]) keyset.primary_key_id = 123 with self.assertRaises(core.TinkError): handle = _keyset_handle(keyset) handle.primitive(aead.Aead)
def test_primitive_fails_on_multiple_primary_keys(self): keyset = tink_pb2.Keyset() keyset.key.extend( [helper.fake_key(key_id=12345), helper.fake_key(key_id=12345)]) keyset.primary_key_id = 12345 handle = core.KeysetHandle(keyset) with self.assertRaisesRegex(core.TinkError, 'keyset contains multiple primary keys'): handle.primitive(aead.Aead)
def test_write_read_with_unicode_chars(self): keyset = tink_pb2.Keyset() key = keyset.key.add() key.key_data.type_url = ( u'\xe3\x82\xb3\xe3\x83\xb3\xe3\x83\x8b\xe3\x83\x81\xe3\x83\x8f') stream = io.StringIO() writer = tink.JsonKeysetWriter(stream) writer.write(keyset) reader = tink.JsonKeysetReader(stream.getvalue()) self.assertEqual(keyset, reader.read())
def public_keyset_handle(self) -> 'KeysetHandle': """Returns a new KeysetHandle for the corresponding public keys.""" public_keyset = tink_pb2.Keyset() for key in self._keyset.key: public_key = public_keyset.key.add() public_key.CopyFrom(key) public_key.key_data.CopyFrom( registry.Registry.public_key_data(key.key_data)) _validate_key(public_key) public_keyset.primary_key_id = self._keyset.primary_key_id return KeysetHandle(public_keyset)
def example_keyset() -> tink_pb2.Keyset: keyset = tink_pb2.Keyset() keyset.primary_key_id = 42 key = keyset.key.add() key.key_data.type_url = u'type.googleapis.com/google.crypto.tink.AesGcmKey' key.key_data.key_material_type = tink_pb2.KeyData.SYMMETRIC key.key_data.value = b'GhCS/1+ejWpx68NfGt6ziYHd' key.output_prefix_type = tink_pb2.TINK key.key_id = 42 key.status = tink_pb2.ENABLED return keyset
def test_init_fails_without_primary_key_present(self): keyset = tink_pb2.Keyset() key = keyset.key.add() key.key_data.CopyFrom( core.Registry.new_key_data(aead.aead_key_templates.AES128_EAX)) key.output_prefix_type = tink_pb2.TINK key.key_id = 2 key.status = tink_pb2.ENABLED keyset.primary_key_id = 1 with self.assertRaisesRegex(core.TinkError, 'keyset does not contain a valid primary key'): _ = _keyset_handle(keyset)
def test_read(self): keyset = tink_pb2.Keyset() keyset.primary_key_id = 42 key = keyset.key.add() key.key_data.type_url = 'type.googleapis.com/google.crypto.tink.AesGcmKey' key.key_data.key_material_type = tink_pb2.KeyData.SYMMETRIC key.key_data.value = b'GhCS/1+ejWpx68NfGt6ziYHd' key.output_prefix_type = tink_pb2.TINK key.key_id = 42 key.status = tink_pb2.ENABLED reader = tink.BinaryKeysetReader(keyset.SerializeToString()) self.assertEqual(keyset, reader.read())
def test_primitive_fails_on_wrong_primitive_class(self): keyset = tink_pb2.Keyset() key = keyset.key.add() key.key_data.CopyFrom( core.Registry.new_key_data(aead.aead_key_templates.AES128_EAX)) key.output_prefix_type = tink_pb2.TINK key.key_id = 1 key.status = tink_pb2.ENABLED keyset.primary_key_id = 1 handle = core.KeysetHandle(keyset) with self.assertRaisesRegex(core.TinkError, 'Wrong primitive class'): handle.primitive(mac.Mac)
def test_primitive_fails_on_wrong_primitive_class(self): keyset = tink_pb2.Keyset() key = keyset.key.add() key.key_data.CopyFrom( core.Registry.new_key_data(aead.aead_key_templates.AES128_EAX)) key.output_prefix_type = tink_pb2.TINK key.key_id = 1 key.status = tink_pb2.ENABLED keyset.primary_key_id = 1 handle = _keyset_handle(keyset) _ = handle.primitive(aead.Aead) # Make sure the handle works for AEAD. with self.assertRaises(core.TinkError): handle.primitive(mac.Mac)
def test_primitive_success(self): keyset = tink_pb2.Keyset() key = keyset.key.add() key.key_data.CopyFrom( core.Registry.new_key_data(aead.aead_key_templates.AES128_EAX)) key.output_prefix_type = tink_pb2.TINK key.key_id = 1 key.status = tink_pb2.ENABLED keyset.primary_key_id = 1 handle = _keyset_handle(keyset) aead_primitive = handle.primitive(aead.Aead) self.assertEqual( aead_primitive.decrypt( aead_primitive.encrypt(b'message', b'aad'), b'aad'), b'message')
def _gen_keyset( type_url: str, value: bytes, key_material_type: tink_pb2.KeyData.KeyMaterialType) -> tink_pb2.Keyset: """Generates a new Keyset.""" keyset = tink_pb2.Keyset() key = keyset.key.add() key.key_data.type_url = type_url key.key_data.value = value key.key_data.key_material_type = key_material_type key.status = tink_pb2.ENABLED key.key_id = 42 key.output_prefix_type = tink_pb2.TINK keyset.primary_key_id = 42 return keyset
def test_to_from_json(self, keyset_text_proto): keyset_proto = text_format.Parse(keyset_text_proto, tink_pb2.Keyset()) keyset = keyset_proto.SerializeToString() for to_lang in testing_servers.LANGUAGES: json_keyset = testing_servers.keyset_to_json(to_lang, keyset) for from_lang in testing_servers.LANGUAGES: keyset_from_json = testing_servers.keyset_from_json( from_lang, json_keyset) key_util.assert_tink_proto_equal( self, tink_pb2.Keyset.FromString(keyset), tink_pb2.Keyset.FromString(keyset_from_json), msg=('keysets are not equal when converting to JSON in ' '%s and back in %s' % (to_lang, from_lang)))
def _keyset() -> bytes: jwt_hmac_key = jwt_hmac_pb2.JwtHmacKey( version=0, algorithm=jwt_hmac_pb2.HS256, key_value=base64.urlsafe_b64decode(KEY_VALUE)) keyset = tink_pb2.Keyset() key = keyset.key.add() key.key_data.type_url = ('type.googleapis.com/google.crypto.tink.JwtHmacKey') key.key_data.value = jwt_hmac_key.SerializeToString() key.key_data.key_material_type = tink_pb2.KeyData.SYMMETRIC key.status = tink_pb2.ENABLED key.key_id = 123 key.output_prefix_type = tink_pb2.RAW keyset.primary_key_id = 123 return keyset.SerializeToString()
def _mac() -> mac.Mac: hmac_key = hmac_pb2.HmacKey( version=0, key_value=base64.urlsafe_b64decode(KEY_VALUE)) hmac_key.params.hash = common_pb2.SHA256 hmac_key.params.tag_size = 32 keyset = tink_pb2.Keyset() key = keyset.key.add() key.key_data.type_url = ('type.googleapis.com/google.crypto.tink.HmacKey') key.key_data.value = hmac_key.SerializeToString() key.key_data.key_material_type = tink_pb2.KeyData.SYMMETRIC key.status = tink_pb2.ENABLED key.key_id = 123 key.output_prefix_type = tink_pb2.RAW keyset.primary_key_id = 123 keyset_handle = cleartext_keyset_handle.from_keyset(keyset) return keyset_handle.primitive(mac.Mac)
def to_public_keyset_handle(jwk_set: str) -> tink.KeysetHandle: """Converts a Json Web Key (JWK) set into a Tink KeysetHandle with JWT keys. JWK is defined in https://www.rfc-editor.org/rfc/rfc7517.txt. All keys are converted into Tink keys with output prefix type "RAW". Currently, public keys for algorithms ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384 and PS512 supported. Args: jwk_set: A JWK set, which is a JSON encoded string. Returns: A tink.KeysetHandle. Raises: TinkError if the key cannot be converted. """ try: keys_dict = json.loads(jwk_set) except json.decoder.JSONDecodeError as e: raise tink.TinkError('error parsing JWK set: %s' % e.msg) if 'keys' not in keys_dict: raise tink.TinkError('invalid JWK set: keys not found') proto_keyset = tink_pb2.Keyset() for key in keys_dict['keys']: if 'alg' not in key: raise tink.TinkError('invalid JWK: alg not found') alg = key['alg'] if alg.startswith('ES'): proto_key = _convert_to_ecdsa_key(key) elif alg.startswith('RS'): proto_key = _convert_to_rsa_ssa_pkcs1_key(key) elif alg.startswith('PS'): proto_key = _convert_to_rsa_ssa_pss_key(key) else: raise tink.TinkError('unknown alg') new_id = _generate_unused_key_id(proto_keyset) proto_key.key_id = new_id proto_keyset.key.append(proto_key) # JWK sets do not really have a primary key (see RFC 7517, Section 5.1). # To verify signature, it also does not matter which key is primary. We # simply set it to the last key. proto_keyset.primary_key_id = new_id return cleartext_keyset_handle.from_keyset(proto_keyset)
def read_write_encrypted_test_cases( ) -> Iterable[Tuple[str, bytes, str, str, str, str, Optional[bytes]]]: """Yields (test_name, test_parameters...) tuples to test.""" for keyset_name, keyset_text_proto in TEST_KEYSETS: keyset_proto = text_format.Parse(keyset_text_proto, tink_pb2.Keyset()) keyset = keyset_proto.SerializeToString() for write_lang in testing_servers.LANGUAGES: for read_lang in testing_servers.LANGUAGES: for associated_data in [None, b'', b'associated_data']: yield ( '_bin_%s, r in %s, w in %s, ad=%s' % (keyset_name, read_lang, write_lang, associated_data), keyset, read_lang, 'KEYSET_READER_BINARY', write_lang, 'KEYSET_WRITER_BINARY', associated_data) yield ( '_json_%s, r in %s, w in %s, ad=%s' % (keyset_name, write_lang, read_lang, associated_data), keyset, read_lang, 'KEYSET_READER_JSON', write_lang, 'KEYSET_WRITER_JSON', associated_data)
def generate_new(key_template: tink_pb2.KeyTemplate) -> KeysetHandle: """Return a new KeysetHandle. It contains a single fresh key generated according to key_template. Args: key_template: A tink_pb2.KeyTemplate object. Returns: A new KeysetHandle. """ keyset = tink_pb2.Keyset() key_data = registry.Registry.new_key_data(key_template) key_id = _generate_unused_key_id(keyset) key = keyset.key.add() key.key_data.CopyFrom(key_data) key.status = tink_pb2.ENABLED key.key_id = key_id key.output_prefix_type = key_template.output_prefix_type keyset.primary_key_id = key_id return KeysetHandle(keyset)
def test_primitive_wrapped_correctly(self): keydata2 = core.Registry.new_key_data( aead.aead_key_templates.AES128_EAX) keyset = tink_pb2.Keyset() key = keyset.key.add() key.key_data.CopyFrom( core.Registry.new_key_data(aead.aead_key_templates.AES128_EAX)) key.output_prefix_type = tink_pb2.TINK key.key_id = 1 key.status = tink_pb2.ENABLED key = keyset.key.add() key.key_data.CopyFrom(keydata2) key.output_prefix_type = tink_pb2.RAW key.key_id = 2 key.status = tink_pb2.ENABLED keyset.primary_key_id = 1 handle = core.KeysetHandle(keyset) aead_primitive = handle.primitive(aead.Aead) aead_primitive2 = core.Registry.primitive(keydata2, aead.Aead) self.assertEqual( aead_primitive.decrypt(aead_primitive2.encrypt(b'message', b'aad'), b'aad'), b'message')