Source code for pyhpke.kem_key

import json
from typing import Any, Dict, Union

from cryptography.hazmat.primitives.asymmetric.ec import (
    EllipticCurvePrivateKey,
    EllipticCurvePublicKey,
)
from cryptography.hazmat.primitives.asymmetric.x448 import X448PrivateKey, X448PublicKey
from cryptography.hazmat.primitives.asymmetric.x25519 import (
    X25519PrivateKey,
    X25519PublicKey,
)
from cryptography.hazmat.primitives.serialization import (
    load_pem_private_key,
    load_pem_public_key,
)

from .consts import HPKE_SUPPORTED_JWK_KTYS
from .kem_key_interface import KEMKeyInterface
from .keys.ec_key import ECKey
from .keys.x448_key import X448Key
from .keys.x25519_key import X25519Key


[docs] class KEMKey: """ A :class:`KEMKeyInterface <pyhpke.KEMKeyInterface>` Builder. """
[docs] @classmethod def from_pyca_cryptography_key(cls, k: Any) -> KEMKeyInterface: """ Creates an HPKE key from `pyca/cryptography` key object. """ if isinstance(k, EllipticCurvePrivateKey) or isinstance(k, EllipticCurvePublicKey): return ECKey(k) elif isinstance(k, X25519PrivateKey) or isinstance(k, X25519PublicKey): return X25519Key(k) elif isinstance(k, X448PrivateKey) or isinstance(k, X448PublicKey): return X448Key(k) raise ValueError("Unsupported or unknown key.")
[docs] @classmethod def from_jwk(cls, data: Union[bytes, str, Dict[str, Any]]) -> KEMKeyInterface: """ Creates an HPKE key from JWK (JSON Web Key). """ jwk: Dict[str, Any] if not isinstance(data, dict): jwk = json.loads(data) else: jwk = data if "kty" not in jwk: raise ValueError("kty not found.") if jwk["kty"] not in HPKE_SUPPORTED_JWK_KTYS: raise ValueError(f"Unknown kty: {jwk['kty']}.") if jwk["kty"] == "EC": return ECKey.from_jwk(jwk) if jwk["kty"] == "OKP": if "crv" not in jwk: raise ValueError("crv not found.") if jwk["crv"] == "X25519": return X25519Key.from_jwk(jwk) if jwk["crv"] == "X448": return X448Key.from_jwk(jwk) raise ValueError(f"Unsupported or unknown crv: {jwk['crv']}.") raise ValueError("Unsupported or unknown key.")
[docs] @classmethod def from_pem(cls, data: Union[bytes, str]) -> KEMKeyInterface: """ Creates an HPKE key from PEM-formatted key data. """ if isinstance(data, str): data = data.encode("utf-8") data_str = data.decode("utf-8") k: Any = None if "BEGIN PUBLIC" in data_str: k = load_pem_public_key(data) elif "BEGIN PRIVATE" in data_str: k = load_pem_private_key(data, password=None) elif "BEGIN EC PRIVATE" in data_str: k = load_pem_private_key(data, password=None) else: raise ValueError("Failed to decode PEM.") return cls.from_pyca_cryptography_key(k)
[docs] class KEMKeyPair(object): def __init__(self, sk: KEMKeyInterface, pk: KEMKeyInterface): self._sk = sk self._pk = pk return @property def private_key(self) -> KEMKeyInterface: return self._sk @property def public_key(self) -> KEMKeyInterface: return self._pk