def _run(self, operation: Text, input_data: bytes, associated_data: bytes) -> bytes: with tempfile.TemporaryDirectory() as tmpdir: keyset_filename = os.path.join(tmpdir, 'keyset_file') input_filename = os.path.join(tmpdir, 'input_file') associated_data_filename = os.path.join(tmpdir, 'associated_data_file') output_filename = os.path.join(tmpdir, 'output_file') with open(keyset_filename, 'wb') as f: cleartext_keyset_handle.write(tink.BinaryKeysetWriter(f), self._keyset_handle) with open(input_filename, 'wb') as f: f.write(input_data) with open(associated_data_filename, 'wb') as f: f.write(associated_data) try: unused_return_value = subprocess.check_output([ self._cli, keyset_filename, operation, input_filename, associated_data_filename, output_filename ]) except subprocess.CalledProcessError as e: raise tink.TinkError(e) with open(output_filename, 'rb') as f: output_data = f.read() return output_data
def public_keyset_handle(private_keyset_handle) -> tink.KeysetHandle: """Generates a public keyset handle from a private one.""" with tempfile.TemporaryDirectory() as tmpdir: cli_path = os.path.join(_tools_path(), _TINKEY_CLI_PATH) private_keyset_filename = os.path.join(tmpdir, 'private_keyset_file') with open(private_keyset_filename, 'wb') as f: cleartext_keyset_handle.write(tink.BinaryKeysetWriter(f), private_keyset_handle) public_keyset_filename = os.path.join(tmpdir, 'public_keyset_file') unused_return_value = subprocess.check_output([ cli_path, 'create-public-keyset', '--in-format', 'BINARY', '--in', private_keyset_filename, '--out-format', 'BINARY', '--out', public_keyset_filename, ]) with open(public_keyset_filename, 'rb') as f: public_keyset_data = f.read() return cleartext_keyset_handle.read( tink.BinaryKeysetReader(public_keyset_data))
def verify_mac(self, mac_value: bytes, data: bytes) -> None: with tempfile.TemporaryDirectory() as tmpdir: keyset_filename = os.path.join(tmpdir, 'keyset_file') with open(keyset_filename, 'wb') as f: cleartext_keyset_handle.write(tink.BinaryKeysetWriter(f), self._keyset_handle) data_filename = os.path.join(tmpdir, 'data_file') with open(data_filename, 'wb') as f: f.write(data) mac_filename = os.path.join(tmpdir, 'mac_file') with open(mac_filename, 'wb') as f: f.write(mac_value) result_filename = os.path.join(tmpdir, 'result_file') try: unused_return_value = subprocess.check_output([ self._cli, keyset_filename, 'verify', data_filename, mac_filename, result_filename ]) except subprocess.CalledProcessError as e: raise tink.TinkError(e) with open(result_filename, 'rb') as f: result = f.read() if result != b'valid': raise tink.TinkError('verification failed') return None
def test_write_encrypted_read_encrypted(self): encrypted_keyset = example_encrypted_keyset() stream = io.BytesIO() writer = tink.BinaryKeysetWriter(stream) writer.write_encrypted(encrypted_keyset) reader = tink.BinaryKeysetReader(stream.getvalue()) self.assertEqual(encrypted_keyset, reader.read_encrypted())
def verify(self, sign: bytes, data: bytes) -> None: with tempfile.TemporaryDirectory() as tmpdir: public_keyset_filename = os.path.join(tmpdir, 'public_keyset_file') with open(public_keyset_filename, 'wb') as f: cleartext_keyset_handle.write(tink.BinaryKeysetWriter(f), self._public_keyset_handle) signature_filename = os.path.join(tmpdir, 'signature_file') with open(signature_filename, 'wb') as f: f.write(sign) message_filename = os.path.join(tmpdir, 'message_file') with open(message_filename, 'wb') as f: f.write(data) output_filename = os.path.join(tmpdir, 'output_file') try: unused_return_value = subprocess.check_output([ self._cli, public_keyset_filename, signature_filename, message_filename, output_filename ]) except subprocess.CalledProcessError as e: raise tink.TinkError(e) with open(output_filename, 'rb') as f: output = f.read() if output != b'valid': raise tink.TinkError('verification failed') return None
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 ReadEncrypted( self, request: testing_api_pb2.KeysetReadEncryptedRequest, context: grpc.ServicerContext ) -> testing_api_pb2.KeysetReadEncryptedResponse: """Reads an encrypted keyset.""" try: master_keyset_handle = cleartext_keyset_handle.read( tink.BinaryKeysetReader(request.master_keyset)) master_aead = master_keyset_handle.primitive(aead.Aead) if request.keyset_reader_type == testing_api_pb2.KEYSET_READER_BINARY: reader = tink.BinaryKeysetReader(request.encrypted_keyset) elif request.keyset_reader_type == testing_api_pb2.KEYSET_READER_JSON: reader = tink.JsonKeysetReader(request.encrypted_keyset.decode('utf8')) else: raise ValueError('unknown keyset reader type') if request.HasField('associated_data'): keyset_handle = tink.read_keyset_handle_with_associated_data( reader, master_aead, request.associated_data.value) else: keyset_handle = tink.read_keyset_handle(reader, master_aead) keyset = io.BytesIO() cleartext_keyset_handle.write( tink.BinaryKeysetWriter(keyset), keyset_handle) return testing_api_pb2.KeysetReadEncryptedResponse( keyset=keyset.getvalue()) except tink.TinkError as e: return testing_api_pb2.KeysetReadEncryptedResponse(err=str(e))
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_write_encrypted_invalid_fails(self): with self.assertRaisesRegex(core.TinkError, 'invalid encrypted keyset'): stream = io.BytesIO() writer = tink.BinaryKeysetWriter(stream) invalid_encrypted_keyset = cast(tink_pb2.EncryptedKeyset, example_keyset()) writer.write_encrypted(invalid_encrypted_keyset)
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 getKey(self): iostream = io.BytesIO() writer = tink.BinaryKeysetWriter(iostream) if self.gcp_aead != None: self.keyset_handle.write(writer, self.gcp_aead) else: writer.write(self.keyset_handle._keyset) encoded_key = base64.b64encode(iostream.getvalue()).decode('utf-8') return base64.b64encode(iostream.getvalue()).decode('utf-8')
def test_read_no_secret(self): private_handle = tink.new_keyset_handle( hybrid.hybrid_key_templates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM) public_handle = private_handle.public_keyset_handle() output_stream_pub = io.BytesIO() writer = tink.BinaryKeysetWriter(output_stream_pub) writer.write(public_handle._keyset) output_stream_priv = io.BytesIO() writer = tink.BinaryKeysetWriter(output_stream_priv) writer.write(private_handle._keyset) reader = tink.BinaryKeysetReader(output_stream_pub.getvalue()) tink.read_no_secret_keyset_handle(reader) reader = tink.BinaryKeysetReader(output_stream_priv.getvalue()) with self.assertRaises(core.TinkError): tink.read_no_secret_keyset_handle(reader)
def test_write_read(self): handle = tink.new_keyset_handle( mac.mac_key_templates.HMAC_SHA256_128BITTAG) output_stream = io.BytesIO() writer = tink.BinaryKeysetWriter(output_stream) cleartext_keyset_handle.write(writer, handle) reader = tink.BinaryKeysetReader(output_stream.getvalue()) handle2 = cleartext_keyset_handle.read(reader) # 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 _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 test_write_encrypted_with_mismatched_associated_data(self): handle = tink.new_keyset_handle(mac.mac_key_templates.HMAC_SHA256_128BITTAG) # Encrypt the keyset with Aead. master_key_aead = _master_key_aead() output_stream = io.BytesIO() writer = tink.BinaryKeysetWriter(output_stream) handle.write_with_associated_data(writer, master_key_aead, b'01') reader = tink.BinaryKeysetReader(output_stream.getvalue()) with self.assertRaises(core.TinkError): tink.read_keyset_handle_with_associated_data(reader, master_key_aead, b'02')
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 test_write_no_secret(self): private_handle = tink.new_keyset_handle( hybrid.hybrid_key_templates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM) public_handle = private_handle.public_keyset_handle() output_stream = io.BytesIO() writer = tink.BinaryKeysetWriter(output_stream) public_handle.write_no_secret(writer) with self.assertRaises(core.TinkError): private_handle.write_no_secret(writer)
def test_write_encrypted(self): handle = tink.new_keyset_handle(mac.mac_key_templates.HMAC_SHA256_128BITTAG) # Encrypt the keyset with Aead. master_key_aead = _master_key_aead() output_stream = io.BytesIO() writer = tink.BinaryKeysetWriter(output_stream) handle.write(writer, master_key_aead) reader = tink.BinaryKeysetReader(output_stream.getvalue()) handle2 = tink.read_keyset_handle(reader, master_key_aead) # 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 FromJson( self, request: testing_api_pb2.KeysetFromJsonRequest, context: grpc.ServicerContext) -> testing_api_pb2.KeysetFromJsonResponse: """Converts a keyset from JSON to binary format.""" try: keyset_handle = cleartext_keyset_handle.read( tink.JsonKeysetReader(request.json_keyset)) keyset = io.BytesIO() cleartext_keyset_handle.write( tink.BinaryKeysetWriter(keyset), keyset_handle) return testing_api_pb2.KeysetFromJsonResponse(keyset=keyset.getvalue()) except tink.TinkError as e: return testing_api_pb2.KeysetFromJsonResponse(err=str(e))
def Generate( self, request: testing_api_pb2.GenerateKeysetRequest, context: grpc.ServicerContext) -> testing_api_pb2.KeysetResponse: """Generates a keyset.""" try: template = tink_pb2.KeyTemplate() template.ParseFromString(request.template) keyset_handle = tink.new_keyset_handle(template) keyset = io.BytesIO() cleartext_keyset_handle.write( tink.BinaryKeysetWriter(keyset), keyset_handle) return testing_api_pb2.KeysetResponse(keyset=keyset.getvalue()) except tink.TinkError as e: return testing_api_pb2.KeysetResponse(err=str(e))
def WriteEncrypted( self, request: testing_api_pb2.KeysetWriteEncryptedRequest, context: grpc.ServicerContext ) -> testing_api_pb2.KeysetWriteEncryptedResponse: """Writes an encrypted keyset.""" try: master_keyset_handle = cleartext_keyset_handle.read( tink.BinaryKeysetReader(request.master_keyset)) keyset_handle = cleartext_keyset_handle.read( tink.BinaryKeysetReader(request.keyset)) master_aead = master_keyset_handle.primitive(aead.Aead) encrypted_keyset = io.BytesIO() if request.HasField('associated_data'): keyset_handle.write_with_associated_data( tink.BinaryKeysetWriter(encrypted_keyset), master_aead, request.associated_data.value) else: keyset_handle.write(tink.BinaryKeysetWriter(encrypted_keyset), master_aead) return testing_api_pb2.KeysetWriteEncryptedResponse( encrypted_keyset=encrypted_keyset.getvalue()) except tink.TinkError as e: return testing_api_pb2.KeysetWriteEncryptedResponse(err=str(e))
def FromJwkSet( self, request: testing_api_pb2.JwtFromJwkSetRequest, context: grpc.ServicerContext ) -> testing_api_pb2.JwtFromJwkSetResponse: """Converts a JWK set into a Tink Keyset.""" try: keyset_handle = jwt.jwk_set_to_public_keyset_handle( request.jwk_set) keyset = io.BytesIO() cleartext_keyset_handle.write(tink.BinaryKeysetWriter(keyset), keyset_handle) return testing_api_pb2.JwtFromJwkSetResponse( keyset=keyset.getvalue()) except tink.TinkError as e: return testing_api_pb2.JwtFromJwkSetResponse(err=str(e))
def Public( self, request: testing_api_pb2.KeysetPublicRequest, context: grpc.ServicerContext) -> testing_api_pb2.KeysetPublicResponse: """Generates a public-key keyset from a private-key keyset.""" try: private_keyset_handle = cleartext_keyset_handle.read( tink.BinaryKeysetReader(request.private_keyset)) public_keyset_handle = private_keyset_handle.public_keyset_handle() public_keyset = io.BytesIO() cleartext_keyset_handle.write( tink.BinaryKeysetWriter(public_keyset), public_keyset_handle) return testing_api_pb2.KeysetPublicResponse( public_keyset=public_keyset.getvalue()) except tink.TinkError as e: return testing_api_pb2.KeysetPublicResponse(err=str(e))
def from_public_keyset_handle(keyset_handle: tink.KeysetHandle) -> str: """Converts a Tink KeysetHandle with JWT keys into a Json Web Key (JWK) set. JWK is defined in https://www.rfc-editor.org/rfc/rfc7517.txt. Disabled keys are skipped. Keys with output prefix type "TINK" will include the encoded key ID as "kid" value. Keys with output prefix type "RAW" will not have a "kid" value set. Currently, public keys for algorithms ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384 and PS512 supported. Args: keyset_handle: A Tink KeysetHandle that contains JWT Keys. Returns: A JWK set, which is a JSON encoded string. Raises: TinkError if the keys are not of the expected type, or if they have a ouput prefix type that is not supported. """ output_stream = io.BytesIO() writer = tink.BinaryKeysetWriter(output_stream) keyset_handle.write_no_secret(writer) keyset = tink_pb2.Keyset.FromString(output_stream.getvalue()) keys = [] for key in keyset.key: if key.status != tink_pb2.ENABLED: continue if key.key_data.key_material_type != tink_pb2.KeyData.ASYMMETRIC_PUBLIC: raise tink.TinkError('wrong key material type') if key.output_prefix_type not in [tink_pb2.RAW, tink_pb2.TINK]: raise tink.TinkError('unsupported output prefix type') if key.key_data.type_url == _JWT_ECDSA_PUBLIC_KEY_TYPE: keys.append(_convert_jwt_ecdsa_key(key)) elif key.key_data.type_url == _JWT_RSA_SSA_PKCS1_PUBLIC_KEY_TYPE: keys.append(_convert_jwt_rsa_ssa_pkcs1_key(key)) elif key.key_data.type_url == _JWT_RSA_SSA_PSS_PUBLIC_KEY_TYPE: keys.append(_convert_jwt_rsa_ssa_pss_key(key)) else: raise tink.TinkError('unknown key type: %s' % key.key_data.type_url) return json.dumps({'keys': keys}, separators=(',', ':'))
def compute_mac(self, data: bytes) -> bytes: with tempfile.TemporaryDirectory() as tmpdir: keyset_filename = os.path.join(tmpdir, 'keyset_file') with open(keyset_filename, 'wb') as f: cleartext_keyset_handle.write(tink.BinaryKeysetWriter(f), self._keyset_handle) data_filename = os.path.join(tmpdir, 'data_file') with open(data_filename, 'wb') as f: f.write(data) mac_filename = os.path.join(tmpdir, 'mac_file') try: unused_return_value = subprocess.check_output([ self._cli, keyset_filename, 'compute', data_filename, mac_filename ]) except subprocess.CalledProcessError as e: raise tink.TinkError(e) with open(mac_filename, 'rb') as f: mac_value = f.read() return mac_value
def sign(self, message: bytes) -> bytes: with tempfile.TemporaryDirectory() as tmpdir: private_keyset_filename = os.path.join(tmpdir, 'private_keyset_file') with open(private_keyset_filename, 'wb') as f: cleartext_keyset_handle.write(tink.BinaryKeysetWriter(f), self._private_keyset_handle) message_filename = os.path.join(tmpdir, 'message_filename') with open(message_filename, 'wb') as f: f.write(message) output_filename = os.path.join(tmpdir, 'output_file') try: unused_return_value = subprocess.check_output([ self._cli, private_keyset_filename, message_filename, output_filename ]) except subprocess.CalledProcessError as e: raise tink.TinkError(e) with open(output_filename, 'rb') as f: output = f.read() return output
def encrypt(self, plaintext: bytes, context_info: bytes) -> bytes: with tempfile.TemporaryDirectory() as tmpdir: public_keyset_filename = os.path.join(tmpdir, 'public_keyset_file') with open(public_keyset_filename, 'wb') as f: cleartext_keyset_handle.write(tink.BinaryKeysetWriter(f), self._public_keyset_handle) plaintext_filename = os.path.join(tmpdir, 'plaintext_file') with open(plaintext_filename, 'wb') as f: f.write(plaintext) context_info_filename = os.path.join(tmpdir, 'context_info_file') with open(context_info_filename, 'wb') as f: f.write(context_info) ciphertext_filename = os.path.join(tmpdir, 'ciphertext_file') try: unused_return_value = subprocess.check_output([ self._cli, public_keyset_filename, plaintext_filename, context_info_filename, ciphertext_filename ]) except subprocess.CalledProcessError as e: raise tink.TinkError(e) with open(ciphertext_filename, 'rb') as f: ciphertext = f.read() return ciphertext
def test_write_raises_error_when_decrypt_to_wrong_keyset(self): handle = tink.new_keyset_handle(mac.mac_key_templates.HMAC_SHA256_128BITTAG) writer = tink.BinaryKeysetWriter(io.BytesIO()) with self.assertRaises(core.TinkError): handle.write(writer, BadAead2())
def test_write_raises_error_when_encrypt_failed(self): handle = tink.new_keyset_handle(mac.mac_key_templates.HMAC_SHA256_128BITTAG) writer = tink.BinaryKeysetWriter(io.BytesIO()) with self.assertRaises(core.TinkError): handle.write(writer, FaultyAead())
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) return from_keyset(keyset_buffer.getvalue())