Source code for templates.asymmetric_encryption_scheme
"""
Generic classes used for creating an asymmetric encryption scheme.
"""
from __future__ import annotations
import inspect
import sys
from abc import ABC, abstractmethod
from typing import Any, TypeVar
from tno.mpc.encryption_schemes.templates.encryption_scheme import (
CT,
PT,
RP,
EncryptionScheme,
)
if sys.version_info < (3, 11):
from typing_extensions import Self
else:
from typing import Self
[docs]
class PublicKey: # pylint: disable=too-few-public-methods
"""
Public Key of an AsymmetricEncryptionScheme.
This should be subclassed for every AsymmetricEncryptionScheme.
"""
[docs]
class SecretKey: # pylint: disable=too-few-public-methods
"""
Secret Key of an AsymmetricEncryptionScheme.
This should be subclassed for every AsymmetricEncryptionScheme.
"""
PK = TypeVar("PK", bound=PublicKey)
SK = TypeVar("SK", bound=SecretKey)
[docs]
class AsymmetricEncryptionScheme(
EncryptionScheme[tuple[PK, SK], PT, RP, CT],
ABC,
):
"""
Abstract base class for an AsymmetricEncryptionScheme.
"""
[docs]
def __init__(
self,
public_key: PK,
secret_key: SK | None,
*_args: Any,
**_kwargs: Any,
) -> None:
r"""
Construct an AsymmetricEncryptionScheme with the given keypair and optional keyword
arguments. All keyword arguments are combined with the public key to create an ID, so all
the __init__ of a custom subclass of AsymmetricEncryptionScheme should pass all their
parameter values as keyword arguments to this __init__ for the ID generation to work
properly. If this does not happen, then schemes might be considered equal when they are
totally different.
:param public_key: Asymmetric PublicKey.
:param secret_key: Asymmetric SecretKey, might be None when the SecretKey is unknown.
:param \*_args: Optional extra arguments for the constructor of a concrete implementation.
:param \**_kwargs: Optional extra keyword arguments for the constructor of a concrete
implementation.
"""
self.__pk = public_key
self.__sk = secret_key
EncryptionScheme.__init__(self)
[docs]
@classmethod
def from_security_parameter(cls, *args: Any, **kwargs: Any) -> Self:
r"""
Generate a new AsymmetricEncryptionScheme from a security parameter. Note that regular
arguments will be passed to the generate_key_material method, so all parameter that are
required for the constructor should be passed as keyword arguments.
:param \*args: Security parameter(s) for key generation.
:param \**kwargs: Security parameter(s) and optional extra arguments for the constructor.
:raises ValueError: If a keyword argument is not valid for key generation or the
constructor.
:return: A new EncryptionScheme.
"""
gen_names = inspect.getfullargspec(cls.generate_key_material)[0]
init_names = [
name for name in inspect.getfullargspec(cls.__init__)[0] if name != "self"
]
gen_kwargs = {}
init_kwargs = {}
for kwarg, val in kwargs.items():
if kwarg in gen_names:
# arguments used for generating key material
gen_kwargs[kwarg] = val
elif kwarg in init_names:
# arguments used in the __init__ method
init_kwargs[kwarg] = val
else:
raise ValueError(
f"The keyword arguments should either be used for key generation, "
f"or passed to the constructor, but parameter with name {kwarg} "
f"is not present in either."
)
public_key, secret_key = cls.generate_key_material(*args, **gen_kwargs)
return cls(public_key, secret_key, **init_kwargs)
[docs]
@classmethod
@abstractmethod
def generate_key_material(cls, *args: Any, **kwargs: Any) -> tuple[PK, SK]:
r"""
Method to generate key material (PublicKey and SecretKey) for this scheme.
:param \*args: Required arguments to generate said key material.
:param \**kwargs: Required arguments to generate said key material.
:return: Tuple containing first the PublicKey of this scheme and then the SecretKey.
"""
@property
def public_key(self) -> PK:
"""
PublicKey of this instantiation of the scheme.
:return: PublicKey of this instantiation.
"""
return self.__pk
@property
def secret_key(self) -> SK | None:
"""
SecretKey of this instantiation of the scheme.
:return: SecretKey of this instantiation, or None when it is unknown.
"""
return self.__sk