from abc import ABC, abstractmethod from dataclasses import dataclass from enum import Enum, unique from .pb import crypto_pb2 as protobuf @unique class KeyType(Enum): RSA = 0 Ed25519 = 1 Secp256k1 = 2 ECDSA = 3 ECC_P256 = 4 class Key(ABC): """A ``Key`` represents a cryptographic key.""" @abstractmethod def to_bytes(self) -> bytes: """Returns the byte representation of this key.""" ... @abstractmethod def get_type(self) -> KeyType: """Returns the ``KeyType`` for ``self``.""" ... def __eq__(self, other: object) -> bool: if not isinstance(other, Key): return NotImplemented return self.to_bytes() == other.to_bytes() class PublicKey(Key): """A ``PublicKey`` represents a cryptographic public key.""" @abstractmethod def verify(self, data: bytes, signature: bytes) -> bool: """Verify that ``signature`` is the cryptographic signature of the hash of ``data``.""" ... def _serialize_to_protobuf(self) -> protobuf.PublicKey: """Return the protobuf representation of this ``Key``.""" key_type = self.get_type().value data = self.to_bytes() protobuf_key = protobuf.PublicKey(key_type=key_type, data=data) return protobuf_key def serialize(self) -> bytes: """Return the canonical serialization of this ``Key``.""" return self._serialize_to_protobuf().SerializeToString() @classmethod def deserialize_from_protobuf(cls, protobuf_data: bytes) -> protobuf.PublicKey: return protobuf.PublicKey.FromString(protobuf_data) class PrivateKey(Key): """A ``PrivateKey`` represents a cryptographic private key.""" @abstractmethod def sign(self, data: bytes) -> bytes: ... @abstractmethod def get_public_key(self) -> PublicKey: ... def _serialize_to_protobuf(self) -> protobuf.PrivateKey: """Return the protobuf representation of this ``Key``.""" key_type = self.get_type().value data = self.to_bytes() protobuf_key = protobuf.PrivateKey(key_type=key_type, data=data) return protobuf_key def serialize(self) -> bytes: """Return the canonical serialization of this ``Key``.""" return self._serialize_to_protobuf().SerializeToString() @classmethod def deserialize_from_protobuf(cls, protobuf_data: bytes) -> protobuf.PrivateKey: return protobuf.PrivateKey.FromString(protobuf_data) @dataclass(frozen=True) class KeyPair: private_key: PrivateKey public_key: PublicKey