def test_wrapped_encrypt_decrypt_two_keys(self, input_stream_factory): template = (streaming_aead.streaming_aead_key_templates. AES128_CTR_HMAC_SHA256_4KB) old_keyset = tink_pb2.Keyset() key1 = old_keyset.key.add() key1.key_data.CopyFrom(tink.core.Registry.new_key_data(template)) key1.status = tink_pb2.ENABLED key1.key_id = 1234 key1.output_prefix_type = template.output_prefix_type old_keyset.primary_key_id = key1.key_id old_keyset_handle = cleartext_keyset_handle.from_keyset(old_keyset) old_primitive = old_keyset_handle.primitive( streaming_aead.StreamingAead) new_keyset = tink_pb2.Keyset() new_keyset.CopyFrom(old_keyset) key2 = new_keyset.key.add() key2.key_data.CopyFrom(tink.core.Registry.new_key_data(template)) key2.status = tink_pb2.ENABLED key2.key_id = 5678 key2.output_prefix_type = template.output_prefix_type new_keyset.primary_key_id = key2.key_id new_keyset_handle = cleartext_keyset_handle.from_keyset(new_keyset) new_primitive = new_keyset_handle.primitive( streaming_aead.StreamingAead) plaintext1 = b' '.join(b'%d' % i for i in range(100 * 1000)) ciphertext1_dest = bytes_io.BytesIOWithValueAfterClose() with old_primitive.new_encrypting_stream(ciphertext1_dest, b'aad1') as es: es.write(plaintext1) ciphertext1 = ciphertext1_dest.value_after_close() plaintext2 = b' '.join(b'%d' % i for i in range(100 * 1001)) ciphertext2_dest = bytes_io.BytesIOWithValueAfterClose() with new_primitive.new_encrypting_stream(ciphertext2_dest, b'aad2') as es: es.write(plaintext2) ciphertext2 = ciphertext2_dest.value_after_close() # old_primitive can read 1st ciphertext, but not the 2nd with old_primitive.new_decrypting_stream( cast(BinaryIO, input_stream_factory(ciphertext1)), b'aad1') as ds: self.assertEqual(ds.read(), plaintext1) with old_primitive.new_decrypting_stream( cast(BinaryIO, input_stream_factory(ciphertext2)), b'aad2') as ds: with self.assertRaises(tink.TinkError): ds.read() # new_primitive can read both ciphertexts with new_primitive.new_decrypting_stream( cast(BinaryIO, input_stream_factory(ciphertext1)), b'aad1') as ds: self.assertEqual(ds.read(), plaintext1) with new_primitive.new_decrypting_stream( cast(BinaryIO, input_stream_factory(ciphertext2)), b'aad2') as ds: self.assertEqual(ds.read(), plaintext2)
def _set_custom_kid(keyset_handle: tink.KeysetHandle, custom_kid: str) -> tink.KeysetHandle: """Sets the custom_kid field of the first key.""" buffer = io.BytesIO() cleartext_keyset_handle.write( tink.BinaryKeysetWriter(buffer), keyset_handle) keyset = tink_pb2.Keyset.FromString(buffer.getvalue()) if keyset.key[0].key_data.type_url.endswith('JwtEcdsaPrivateKey'): jwt_ecdsa_key = jwt_ecdsa_pb2.JwtEcdsaPrivateKey.FromString( keyset.key[0].key_data.value) jwt_ecdsa_key.public_key.custom_kid.value = custom_kid keyset.key[0].key_data.value = jwt_ecdsa_key.SerializeToString() elif keyset.key[0].key_data.type_url.endswith('JwtRsaSsaPkcs1PrivateKey'): rsa_key = jwt_rsa_ssa_pkcs1_pb2.JwtRsaSsaPkcs1PrivateKey.FromString( keyset.key[0].key_data.value) rsa_key.public_key.custom_kid.value = custom_kid keyset.key[0].key_data.value = rsa_key.SerializeToString() elif keyset.key[0].key_data.type_url.endswith('JwtRsaSsaPssPrivateKey'): rsa_key = jwt_rsa_ssa_pss_pb2.JwtRsaSsaPssPrivateKey.FromString( keyset.key[0].key_data.value) rsa_key.public_key.custom_kid.value = custom_kid keyset.key[0].key_data.value = rsa_key.SerializeToString() else: raise tink.TinkError('unknown key type') return cleartext_keyset_handle.from_keyset(keyset)
def test_from_keyset(self): handle = tink.new_keyset_handle( mac.mac_key_templates.HMAC_SHA256_128BITTAG) keyset = handle._keyset handle2 = cleartext_keyset_handle.from_keyset(keyset) # Check that handle2 has the same primitive as handle. handle2.primitive(mac.Mac).verify_mac( handle.primitive(mac.Mac).compute_mac(b'data'), b'data')
def _change_output_prefix_to_tink( keyset_handle: tink.KeysetHandle) -> tink.KeysetHandle: """Changes the output prefix type of the first key to TINK.""" buffer = io.BytesIO() cleartext_keyset_handle.write( tink.BinaryKeysetWriter(buffer), keyset_handle) keyset = tink_pb2.Keyset.FromString(buffer.getvalue()) keyset.key[0].output_prefix_type = tink_pb2.TINK return cleartext_keyset_handle.from_keyset(keyset)
def _change_key_id(keyset_handle: tink.KeysetHandle) -> tink.KeysetHandle: """Changes the key id of the first key and makes it primary.""" buffer = io.BytesIO() cleartext_keyset_handle.write( tink.BinaryKeysetWriter(buffer), keyset_handle) keyset = tink_pb2.Keyset.FromString(buffer.getvalue()) # XOR the key id with an arbitrary 32-bit string to get a new key id. new_key_id = keyset.key[0].key_id ^ 0xdeadbeef keyset.key[0].key_id = new_key_id keyset.primary_key_id = new_key_id return cleartext_keyset_handle.from_keyset(keyset)
def _set_custom_kid(keyset_handle: tink.KeysetHandle, custom_kid: str) -> tink.KeysetHandle: """Set the custom_kid field of the first key.""" buffer = io.BytesIO() cleartext_keyset_handle.write(tink.BinaryKeysetWriter(buffer), keyset_handle) keyset = tink_pb2.Keyset.FromString(buffer.getvalue()) hmac_key = jwt_hmac_pb2.JwtHmacKey.FromString(keyset.key[0].key_data.value) hmac_key.custom_kid.value = custom_kid keyset.key[0].key_data.value = hmac_key.SerializeToString() return cleartext_keyset_handle.from_keyset(keyset)
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 keyset_handle(self) -> tink.KeysetHandle: keyset_copy = tink_pb2.Keyset() keyset_copy.CopyFrom(self._keyset) return cleartext_keyset_handle.from_keyset(keyset_copy)
def generate_keyset_handle(key_template) -> tink.KeysetHandle: """Generates a keyset handle from a key templates.""" return cleartext_keyset_handle.from_keyset(generate_keyset(key_template))