Exemplo n.º 1
0
 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
Exemplo n.º 2
0
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))
Exemplo n.º 3
0
 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
Exemplo n.º 4
0
 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())
Exemplo n.º 5
0
 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)
Exemplo n.º 7
0
  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))
Exemplo n.º 8
0
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)
Exemplo n.º 9
0
 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)
Exemplo n.º 10
0
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)
Exemplo n.º 11
0
 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')
Exemplo n.º 12
0
  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)
Exemplo n.º 13
0
 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')
Exemplo n.º 14
0
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)
Exemplo n.º 15
0
 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')
Exemplo n.º 16
0
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)
Exemplo n.º 17
0
  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)
Exemplo n.º 18
0
 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')
Exemplo n.º 19
0
 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))
Exemplo n.º 20
0
 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))
Exemplo n.º 21
0
    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))
Exemplo n.º 22
0
 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))
Exemplo n.º 23
0
 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))
Exemplo n.º 24
0
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=(',', ':'))
Exemplo n.º 25
0
 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
Exemplo n.º 26
0
 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
Exemplo n.º 27
0
 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
Exemplo n.º 28
0
 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())
Exemplo n.º 29
0
 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())
Exemplo n.º 30
0
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())