| from typing import Dict, Optional, Tuple, Type, Union | |
| import dns.name | |
| from dns.dnssecalgs.base import GenericPrivateKey | |
| from dns.dnssectypes import Algorithm | |
| from dns.exception import UnsupportedAlgorithm | |
| from dns.rdtypes.ANY.DNSKEY import DNSKEY | |
| if dns._features.have("dnssec"): | |
| from dns.dnssecalgs.dsa import PrivateDSA, PrivateDSANSEC3SHA1 | |
| from dns.dnssecalgs.ecdsa import PrivateECDSAP256SHA256, PrivateECDSAP384SHA384 | |
| from dns.dnssecalgs.eddsa import PrivateED448, PrivateED25519 | |
| from dns.dnssecalgs.rsa import ( | |
| PrivateRSAMD5, | |
| PrivateRSASHA1, | |
| PrivateRSASHA1NSEC3SHA1, | |
| PrivateRSASHA256, | |
| PrivateRSASHA512, | |
| ) | |
| _have_cryptography = True | |
| else: | |
| _have_cryptography = False | |
| AlgorithmPrefix = Optional[Union[bytes, dns.name.Name]] | |
| algorithms: Dict[Tuple[Algorithm, AlgorithmPrefix], Type[GenericPrivateKey]] = {} | |
| if _have_cryptography: | |
| algorithms.update( | |
| { | |
| (Algorithm.RSAMD5, None): PrivateRSAMD5, | |
| (Algorithm.DSA, None): PrivateDSA, | |
| (Algorithm.RSASHA1, None): PrivateRSASHA1, | |
| (Algorithm.DSANSEC3SHA1, None): PrivateDSANSEC3SHA1, | |
| (Algorithm.RSASHA1NSEC3SHA1, None): PrivateRSASHA1NSEC3SHA1, | |
| (Algorithm.RSASHA256, None): PrivateRSASHA256, | |
| (Algorithm.RSASHA512, None): PrivateRSASHA512, | |
| (Algorithm.ECDSAP256SHA256, None): PrivateECDSAP256SHA256, | |
| (Algorithm.ECDSAP384SHA384, None): PrivateECDSAP384SHA384, | |
| (Algorithm.ED25519, None): PrivateED25519, | |
| (Algorithm.ED448, None): PrivateED448, | |
| } | |
| ) | |
| def get_algorithm_cls( | |
| algorithm: Union[int, str], prefix: AlgorithmPrefix = None | |
| ) -> Type[GenericPrivateKey]: | |
| """Get Private Key class from Algorithm. | |
| *algorithm*, a ``str`` or ``int`` specifying the DNSKEY algorithm. | |
| Raises ``UnsupportedAlgorithm`` if the algorithm is unknown. | |
| Returns a ``dns.dnssecalgs.GenericPrivateKey`` | |
| """ | |
| algorithm = Algorithm.make(algorithm) | |
| cls = algorithms.get((algorithm, prefix)) | |
| if cls: | |
| return cls | |
| raise UnsupportedAlgorithm( | |
| 'algorithm "%s" not supported by dnspython' % Algorithm.to_text(algorithm) | |
| ) | |
| def get_algorithm_cls_from_dnskey(dnskey: DNSKEY) -> Type[GenericPrivateKey]: | |
| """Get Private Key class from DNSKEY. | |
| *dnskey*, a ``DNSKEY`` to get Algorithm class for. | |
| Raises ``UnsupportedAlgorithm`` if the algorithm is unknown. | |
| Returns a ``dns.dnssecalgs.GenericPrivateKey`` | |
| """ | |
| prefix: AlgorithmPrefix = None | |
| if dnskey.algorithm == Algorithm.PRIVATEDNS: | |
| prefix, _ = dns.name.from_wire(dnskey.key, 0) | |
| elif dnskey.algorithm == Algorithm.PRIVATEOID: | |
| length = int(dnskey.key[0]) | |
| prefix = dnskey.key[0 : length + 1] | |
| return get_algorithm_cls(dnskey.algorithm, prefix) | |
| def register_algorithm_cls( | |
| algorithm: Union[int, str], | |
| algorithm_cls: Type[GenericPrivateKey], | |
| name: Optional[Union[dns.name.Name, str]] = None, | |
| oid: Optional[bytes] = None, | |
| ) -> None: | |
| """Register Algorithm Private Key class. | |
| *algorithm*, a ``str`` or ``int`` specifying the DNSKEY algorithm. | |
| *algorithm_cls*: A `GenericPrivateKey` class. | |
| *name*, an optional ``dns.name.Name`` or ``str``, for for PRIVATEDNS algorithms. | |
| *oid*: an optional BER-encoded `bytes` for PRIVATEOID algorithms. | |
| Raises ``ValueError`` if a name or oid is specified incorrectly. | |
| """ | |
| if not issubclass(algorithm_cls, GenericPrivateKey): | |
| raise TypeError("Invalid algorithm class") | |
| algorithm = Algorithm.make(algorithm) | |
| prefix: AlgorithmPrefix = None | |
| if algorithm == Algorithm.PRIVATEDNS: | |
| if name is None: | |
| raise ValueError("Name required for PRIVATEDNS algorithms") | |
| if isinstance(name, str): | |
| name = dns.name.from_text(name) | |
| prefix = name | |
| elif algorithm == Algorithm.PRIVATEOID: | |
| if oid is None: | |
| raise ValueError("OID required for PRIVATEOID algorithms") | |
| prefix = bytes([len(oid)]) + oid | |
| elif name: | |
| raise ValueError("Name only supported for PRIVATEDNS algorithm") | |
| elif oid: | |
| raise ValueError("OID only supported for PRIVATEOID algorithm") | |
| algorithms[(algorithm, prefix)] = algorithm_cls | |