85 lines
2.4 KiB
Python
85 lines
2.4 KiB
Python
|
from abc import ABC, abstractmethod # pylint: disable=no-name-in-module
|
||
|
from typing import Any, Optional, Type
|
||
|
|
||
|
import dns.rdataclass
|
||
|
import dns.rdatatype
|
||
|
from dns.dnssectypes import Algorithm
|
||
|
from dns.exception import AlgorithmKeyMismatch
|
||
|
from dns.rdtypes.ANY.DNSKEY import DNSKEY
|
||
|
from dns.rdtypes.dnskeybase import Flag
|
||
|
|
||
|
|
||
|
class GenericPublicKey(ABC):
|
||
|
algorithm: Algorithm
|
||
|
|
||
|
@abstractmethod
|
||
|
def __init__(self, key: Any) -> None:
|
||
|
pass
|
||
|
|
||
|
@abstractmethod
|
||
|
def verify(self, signature: bytes, data: bytes) -> None:
|
||
|
"""Verify signed DNSSEC data"""
|
||
|
|
||
|
@abstractmethod
|
||
|
def encode_key_bytes(self) -> bytes:
|
||
|
"""Encode key as bytes for DNSKEY"""
|
||
|
|
||
|
@classmethod
|
||
|
def _ensure_algorithm_key_combination(cls, key: DNSKEY) -> None:
|
||
|
if key.algorithm != cls.algorithm:
|
||
|
raise AlgorithmKeyMismatch
|
||
|
|
||
|
def to_dnskey(self, flags: int = Flag.ZONE, protocol: int = 3) -> DNSKEY:
|
||
|
"""Return public key as DNSKEY"""
|
||
|
return DNSKEY(
|
||
|
rdclass=dns.rdataclass.IN,
|
||
|
rdtype=dns.rdatatype.DNSKEY,
|
||
|
flags=flags,
|
||
|
protocol=protocol,
|
||
|
algorithm=self.algorithm,
|
||
|
key=self.encode_key_bytes(),
|
||
|
)
|
||
|
|
||
|
@classmethod
|
||
|
@abstractmethod
|
||
|
def from_dnskey(cls, key: DNSKEY) -> "GenericPublicKey":
|
||
|
"""Create public key from DNSKEY"""
|
||
|
|
||
|
@classmethod
|
||
|
@abstractmethod
|
||
|
def from_pem(cls, public_pem: bytes) -> "GenericPublicKey":
|
||
|
"""Create public key from PEM-encoded SubjectPublicKeyInfo as specified
|
||
|
in RFC 5280"""
|
||
|
|
||
|
@abstractmethod
|
||
|
def to_pem(self) -> bytes:
|
||
|
"""Return public-key as PEM-encoded SubjectPublicKeyInfo as specified
|
||
|
in RFC 5280"""
|
||
|
|
||
|
|
||
|
class GenericPrivateKey(ABC):
|
||
|
public_cls: Type[GenericPublicKey]
|
||
|
|
||
|
@abstractmethod
|
||
|
def __init__(self, key: Any) -> None:
|
||
|
pass
|
||
|
|
||
|
@abstractmethod
|
||
|
def sign(self, data: bytes, verify: bool = False) -> bytes:
|
||
|
"""Sign DNSSEC data"""
|
||
|
|
||
|
@abstractmethod
|
||
|
def public_key(self) -> "GenericPublicKey":
|
||
|
"""Return public key instance"""
|
||
|
|
||
|
@classmethod
|
||
|
@abstractmethod
|
||
|
def from_pem(
|
||
|
cls, private_pem: bytes, password: Optional[bytes] = None
|
||
|
) -> "GenericPrivateKey":
|
||
|
"""Create private key from PEM-encoded PKCS#8"""
|
||
|
|
||
|
@abstractmethod
|
||
|
def to_pem(self, password: Optional[bytes] = None) -> bytes:
|
||
|
"""Return private key as PEM-encoded PKCS#8"""
|