2019-08-14 09:17:08 +08:00
|
|
|
from abc import ABC, abstractmethod
|
2019-08-14 11:23:07 +08:00
|
|
|
from dataclasses import dataclass
|
2019-08-14 09:17:08 +08:00
|
|
|
from enum import Enum, unique
|
|
|
|
|
|
|
|
from .pb import crypto_pb2 as protobuf
|
|
|
|
|
|
|
|
|
|
|
|
@unique
|
|
|
|
class KeyType(Enum):
|
|
|
|
RSA = 0
|
|
|
|
Ed25519 = 1
|
|
|
|
Secp256k1 = 2
|
|
|
|
ECDSA = 3
|
2019-08-23 22:54:16 +08:00
|
|
|
ECC_P256 = 4
|
2019-08-14 09:17:08 +08:00
|
|
|
|
|
|
|
|
2019-08-15 00:25:54 +08:00
|
|
|
class Key(ABC):
|
2019-08-14 09:17:08 +08:00
|
|
|
"""
|
|
|
|
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``.
|
|
|
|
"""
|
|
|
|
...
|
|
|
|
|
2019-08-24 05:43:36 +08:00
|
|
|
def __eq__(self, other: object) -> bool:
|
|
|
|
if not isinstance(other, Key):
|
|
|
|
return NotImplemented
|
|
|
|
return self.to_bytes() == other.to_bytes()
|
2019-08-24 04:12:13 +08:00
|
|
|
|
2019-08-21 01:28:32 +08:00
|
|
|
|
|
|
|
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``.
|
|
|
|
"""
|
|
|
|
...
|
|
|
|
|
2019-08-21 01:01:36 +08:00
|
|
|
def _serialize_to_protobuf(self) -> protobuf.PublicKey:
|
|
|
|
"""
|
|
|
|
Return the protobuf representation of this ``Key``.
|
|
|
|
"""
|
|
|
|
key_type = self.get_type().value
|
|
|
|
data = self.to_bytes()
|
2019-08-21 01:28:32 +08:00
|
|
|
protobuf_key = protobuf.PublicKey(key_type=key_type, data=data)
|
2019-08-21 01:01:36 +08:00
|
|
|
return protobuf_key
|
|
|
|
|
|
|
|
def serialize(self) -> bytes:
|
|
|
|
"""
|
|
|
|
Return the canonical serialization of this ``Key``.
|
|
|
|
"""
|
|
|
|
return self._serialize_to_protobuf().SerializeToString()
|
|
|
|
|
2019-08-24 04:12:13 +08:00
|
|
|
@classmethod
|
|
|
|
def deserialize_from_protobuf(cls, protobuf_data: bytes) -> protobuf.PublicKey:
|
2019-08-24 05:43:36 +08:00
|
|
|
return protobuf.PublicKey.FromString(protobuf_data)
|
2019-08-24 04:12:13 +08:00
|
|
|
|
2019-08-14 09:17:08 +08:00
|
|
|
|
2019-08-15 00:30:23 +08:00
|
|
|
class PrivateKey(Key):
|
2019-08-14 09:17:08 +08:00
|
|
|
"""
|
|
|
|
A ``PrivateKey`` represents a cryptographic private key.
|
|
|
|
"""
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def sign(self, data: bytes) -> bytes:
|
|
|
|
...
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_public_key(self) -> PublicKey:
|
|
|
|
...
|
|
|
|
|
2019-08-21 01:28:32 +08:00
|
|
|
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()
|
|
|
|
|
2019-08-24 04:12:13 +08:00
|
|
|
@classmethod
|
|
|
|
def deserialize_from_protobuf(cls, protobuf_data: bytes) -> protobuf.PrivateKey:
|
2019-08-24 05:43:36 +08:00
|
|
|
return protobuf.PrivateKey.FromString(protobuf_data)
|
2019-08-24 04:12:13 +08:00
|
|
|
|
2019-08-14 11:23:07 +08:00
|
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
|
|
class KeyPair:
|
|
|
|
private_key: PrivateKey
|
|
|
|
public_key: PublicKey
|