Skip to content
Snippets Groups Projects
key_manager.py 4.98 KiB
Newer Older
juerg's avatar
juerg committed
# Copyright 2019 Google LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""This module defines the basic types and abstract classes in Tink."""
from __future__ import absolute_import
from __future__ import division
from __future__ import google_type_annotations
from __future__ import print_function

import abc
from typing import Any, Generic, Text, Type, TypeVar

from tink.proto import tink_pb2
from tink.python.core import tink_error


P = TypeVar('P')


class KeyManager(Generic[P]):
  """Generates keys and provides primitives for the keys.

  A KeyManager "understands" keys of a specific key types: it can generate keys
  of a supported type and create primitives for supported keys.  A key type is
  identified by the global name of the protocol buffer that holds the
  corresponding key material, and is given by type_url-field of KeyData-protocol
  buffer.
  """

  __metaclass__ = abc.ABCMeta

  @abc.abstractmethod
  def primitive_class(self) -> Type[P]:
    """The class of the primitive it uses. Used for internal management."""
    pass

  @abc.abstractmethod
  def primitive(self, key_data: tink_pb2.KeyData) -> P:
    """Constructs an primitive for the given key.

    Args:
      key_data: KeyData protocol buffer
    Returns:
      A primitive, for example an instance of Aead or Mac.
    Raises:
tanujdhir's avatar
tanujdhir committed
      tink.TinkError if getting the primitive fails.
juerg's avatar
juerg committed
    """
    pass

  @abc.abstractmethod
  def key_type(self) -> Text:
    """Returns the type_url identifying the key type handled by this manager."""
    pass

  @abc.abstractmethod
  def new_key_data(self,
                   key_template: tink_pb2.KeyTemplate) -> tink_pb2.KeyData:
    """Generates a new random key, based on the specified key_template.

    Args:
      key_template: KeyTemplate protocol buffer
    Returns:
      A KeyData protocol buffer that contains the key.
    Raises:
tanujdhir's avatar
tanujdhir committed
      tink.TinkError if the key generation fails.
juerg's avatar
juerg committed
    """
    pass

  def does_support(self, type_url: Text) -> bool:
    return self.key_type() == type_url


class PrivateKeyManager(KeyManager[P]):
  """Generates keys and provides primitives for the keys."""

  @abc.abstractmethod
  def public_key_data(
      self, private_key_data: tink_pb2.KeyData) -> tink_pb2.KeyData:
    """Generates a new random key, based on the specified key_template.

    Args:
      private_key_data: KeyData protocol buffer
    Returns:
      A KeyData protocol buffer that contains the public key.
    Raises:
tanujdhir's avatar
tanujdhir committed
      tink.TinkError if the key generation fails.
juerg's avatar
juerg committed
    """
    pass


class KeyManagerCcToPyWrapper(KeyManager[P]):
  """Transforms cliffed C++ KeyManager into a Python KeyManager."""

  def __init__(self,
               cc_key_manager: Any,  # A cliffed CcKeyManager<P> instance
               primitive_class: Type[P],
               primitive_py_wrapper: Type[P]):
    self._cc_key_manager = cc_key_manager
    self._primitive_class = primitive_class
    self._primitive_py_wrapper = primitive_py_wrapper

  def primitive_class(self) -> Type[P]:
    return self._primitive_class

  @tink_error.use_tink_errors
  def primitive(self, key_data: tink_pb2.KeyData) -> P:
    return self._primitive_py_wrapper(self._cc_key_manager.primitive(key_data))

  def key_type(self) -> Text:
    return self._cc_key_manager.key_type()

  @tink_error.use_tink_errors
  def new_key_data(self,
                   key_template: tink_pb2.KeyTemplate) -> tink_pb2.KeyData:
    return self._cc_key_manager.new_key_data(key_template)


class PrivateKeyManagerCcToPyWrapper(PrivateKeyManager[P]):
  """Transforms cliffed C++ KeyManager into a Python KeyManager."""

  def __init__(self,
               cc_key_manager: Any,  # A cliffed CcKeyManager<P> instance
               primitive_class: Type[P],
               primitive_py_wrapper: Type[P]):
    self._cc_key_manager = cc_key_manager
    self._primitive_class = primitive_class
    self._primitive_py_wrapper = primitive_py_wrapper

  def primitive_class(self) -> Type[P]:
    return self._primitive_class

  @tink_error.use_tink_errors
  def primitive(self, key_data: tink_pb2.KeyData) -> P:
    return self._primitive_py_wrapper(self._cc_key_manager.primitive(key_data))

  def key_type(self) -> Text:
    return self._cc_key_manager.key_type()

  @tink_error.use_tink_errors
  def new_key_data(self,
                   key_template: tink_pb2.KeyTemplate) -> tink_pb2.KeyData:
    return self._cc_key_manager.new_key_data(key_template)

  @tink_error.use_tink_errors
  def public_key_data(self, key_data: tink_pb2.KeyData) -> tink_pb2.KeyData:
    return self._cc_key_manager.public_key_data(key_data)