__init__.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. from typing import Dict, Optional, Tuple, Type, Union
  2. import dns.name
  3. from dns.dnssecalgs.base import GenericPrivateKey
  4. from dns.dnssectypes import Algorithm
  5. from dns.exception import UnsupportedAlgorithm
  6. from dns.rdtypes.ANY.DNSKEY import DNSKEY
  7. if dns._features.have("dnssec"):
  8. from dns.dnssecalgs.dsa import PrivateDSA, PrivateDSANSEC3SHA1
  9. from dns.dnssecalgs.ecdsa import PrivateECDSAP256SHA256, PrivateECDSAP384SHA384
  10. from dns.dnssecalgs.eddsa import PrivateED448, PrivateED25519
  11. from dns.dnssecalgs.rsa import (
  12. PrivateRSAMD5,
  13. PrivateRSASHA1,
  14. PrivateRSASHA1NSEC3SHA1,
  15. PrivateRSASHA256,
  16. PrivateRSASHA512,
  17. )
  18. _have_cryptography = True
  19. else:
  20. _have_cryptography = False
  21. AlgorithmPrefix = Optional[Union[bytes, dns.name.Name]]
  22. algorithms: Dict[Tuple[Algorithm, AlgorithmPrefix], Type[GenericPrivateKey]] = {}
  23. if _have_cryptography:
  24. # pylint: disable=possibly-used-before-assignment
  25. algorithms.update(
  26. {
  27. (Algorithm.RSAMD5, None): PrivateRSAMD5,
  28. (Algorithm.DSA, None): PrivateDSA,
  29. (Algorithm.RSASHA1, None): PrivateRSASHA1,
  30. (Algorithm.DSANSEC3SHA1, None): PrivateDSANSEC3SHA1,
  31. (Algorithm.RSASHA1NSEC3SHA1, None): PrivateRSASHA1NSEC3SHA1,
  32. (Algorithm.RSASHA256, None): PrivateRSASHA256,
  33. (Algorithm.RSASHA512, None): PrivateRSASHA512,
  34. (Algorithm.ECDSAP256SHA256, None): PrivateECDSAP256SHA256,
  35. (Algorithm.ECDSAP384SHA384, None): PrivateECDSAP384SHA384,
  36. (Algorithm.ED25519, None): PrivateED25519,
  37. (Algorithm.ED448, None): PrivateED448,
  38. }
  39. )
  40. def get_algorithm_cls(
  41. algorithm: Union[int, str], prefix: AlgorithmPrefix = None
  42. ) -> Type[GenericPrivateKey]:
  43. """Get Private Key class from Algorithm.
  44. *algorithm*, a ``str`` or ``int`` specifying the DNSKEY algorithm.
  45. Raises ``UnsupportedAlgorithm`` if the algorithm is unknown.
  46. Returns a ``dns.dnssecalgs.GenericPrivateKey``
  47. """
  48. algorithm = Algorithm.make(algorithm)
  49. cls = algorithms.get((algorithm, prefix))
  50. if cls:
  51. return cls
  52. raise UnsupportedAlgorithm(
  53. f'algorithm "{Algorithm.to_text(algorithm)}" not supported by dnspython'
  54. )
  55. def get_algorithm_cls_from_dnskey(dnskey: DNSKEY) -> Type[GenericPrivateKey]:
  56. """Get Private Key class from DNSKEY.
  57. *dnskey*, a ``DNSKEY`` to get Algorithm class for.
  58. Raises ``UnsupportedAlgorithm`` if the algorithm is unknown.
  59. Returns a ``dns.dnssecalgs.GenericPrivateKey``
  60. """
  61. prefix: AlgorithmPrefix = None
  62. if dnskey.algorithm == Algorithm.PRIVATEDNS:
  63. prefix, _ = dns.name.from_wire(dnskey.key, 0)
  64. elif dnskey.algorithm == Algorithm.PRIVATEOID:
  65. length = int(dnskey.key[0])
  66. prefix = dnskey.key[0 : length + 1]
  67. return get_algorithm_cls(dnskey.algorithm, prefix)
  68. def register_algorithm_cls(
  69. algorithm: Union[int, str],
  70. algorithm_cls: Type[GenericPrivateKey],
  71. name: Optional[Union[dns.name.Name, str]] = None,
  72. oid: Optional[bytes] = None,
  73. ) -> None:
  74. """Register Algorithm Private Key class.
  75. *algorithm*, a ``str`` or ``int`` specifying the DNSKEY algorithm.
  76. *algorithm_cls*: A `GenericPrivateKey` class.
  77. *name*, an optional ``dns.name.Name`` or ``str``, for for PRIVATEDNS algorithms.
  78. *oid*: an optional BER-encoded `bytes` for PRIVATEOID algorithms.
  79. Raises ``ValueError`` if a name or oid is specified incorrectly.
  80. """
  81. if not issubclass(algorithm_cls, GenericPrivateKey):
  82. raise TypeError("Invalid algorithm class")
  83. algorithm = Algorithm.make(algorithm)
  84. prefix: AlgorithmPrefix = None
  85. if algorithm == Algorithm.PRIVATEDNS:
  86. if name is None:
  87. raise ValueError("Name required for PRIVATEDNS algorithms")
  88. if isinstance(name, str):
  89. name = dns.name.from_text(name)
  90. prefix = name
  91. elif algorithm == Algorithm.PRIVATEOID:
  92. if oid is None:
  93. raise ValueError("OID required for PRIVATEOID algorithms")
  94. prefix = bytes([len(oid)]) + oid
  95. elif name:
  96. raise ValueError("Name only supported for PRIVATEDNS algorithm")
  97. elif oid:
  98. raise ValueError("OID only supported for PRIVATEOID algorithm")
  99. algorithms[(algorithm, prefix)] = algorithm_cls