dh.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. # This file is dual licensed under the terms of the Apache License, Version
  2. # 2.0, and the BSD License. See the LICENSE file in the root of this repository
  3. # for complete details.
  4. import abc
  5. import typing
  6. from cryptography import utils
  7. from cryptography.hazmat.backends import _get_backend
  8. from cryptography.hazmat.primitives import serialization
  9. _MIN_MODULUS_SIZE = 512
  10. def generate_parameters(generator, key_size, backend=None) -> "DHParameters":
  11. backend = _get_backend(backend)
  12. return backend.generate_dh_parameters(generator, key_size)
  13. class DHParameterNumbers(object):
  14. def __init__(self, p: int, g: int, q: typing.Optional[int] = None):
  15. if not isinstance(p, int) or not isinstance(g, int):
  16. raise TypeError("p and g must be integers")
  17. if q is not None and not isinstance(q, int):
  18. raise TypeError("q must be integer or None")
  19. if g < 2:
  20. raise ValueError("DH generator must be 2 or greater")
  21. if p.bit_length() < _MIN_MODULUS_SIZE:
  22. raise ValueError(
  23. "p (modulus) must be at least {}-bit".format(_MIN_MODULUS_SIZE)
  24. )
  25. self._p = p
  26. self._g = g
  27. self._q = q
  28. def __eq__(self, other):
  29. if not isinstance(other, DHParameterNumbers):
  30. return NotImplemented
  31. return (
  32. self._p == other._p and self._g == other._g and self._q == other._q
  33. )
  34. def __ne__(self, other):
  35. return not self == other
  36. def parameters(self, backend=None):
  37. backend = _get_backend(backend)
  38. return backend.load_dh_parameter_numbers(self)
  39. p = utils.read_only_property("_p")
  40. g = utils.read_only_property("_g")
  41. q = utils.read_only_property("_q")
  42. class DHPublicNumbers(object):
  43. def __init__(self, y, parameter_numbers: DHParameterNumbers):
  44. if not isinstance(y, int):
  45. raise TypeError("y must be an integer.")
  46. if not isinstance(parameter_numbers, DHParameterNumbers):
  47. raise TypeError(
  48. "parameters must be an instance of DHParameterNumbers."
  49. )
  50. self._y = y
  51. self._parameter_numbers = parameter_numbers
  52. def __eq__(self, other):
  53. if not isinstance(other, DHPublicNumbers):
  54. return NotImplemented
  55. return (
  56. self._y == other._y
  57. and self._parameter_numbers == other._parameter_numbers
  58. )
  59. def __ne__(self, other):
  60. return not self == other
  61. def public_key(self, backend=None) -> "DHPublicKey":
  62. backend = _get_backend(backend)
  63. return backend.load_dh_public_numbers(self)
  64. y = utils.read_only_property("_y")
  65. parameter_numbers = utils.read_only_property("_parameter_numbers")
  66. class DHPrivateNumbers(object):
  67. def __init__(self, x, public_numbers: DHPublicNumbers):
  68. if not isinstance(x, int):
  69. raise TypeError("x must be an integer.")
  70. if not isinstance(public_numbers, DHPublicNumbers):
  71. raise TypeError(
  72. "public_numbers must be an instance of " "DHPublicNumbers."
  73. )
  74. self._x = x
  75. self._public_numbers = public_numbers
  76. def __eq__(self, other):
  77. if not isinstance(other, DHPrivateNumbers):
  78. return NotImplemented
  79. return (
  80. self._x == other._x
  81. and self._public_numbers == other._public_numbers
  82. )
  83. def __ne__(self, other):
  84. return not self == other
  85. def private_key(self, backend=None) -> "DHPrivateKey":
  86. backend = _get_backend(backend)
  87. return backend.load_dh_private_numbers(self)
  88. public_numbers = utils.read_only_property("_public_numbers")
  89. x = utils.read_only_property("_x")
  90. class DHParameters(metaclass=abc.ABCMeta):
  91. @abc.abstractmethod
  92. def generate_private_key(self) -> "DHPrivateKey":
  93. """
  94. Generates and returns a DHPrivateKey.
  95. """
  96. @abc.abstractmethod
  97. def parameter_bytes(
  98. self,
  99. encoding: "serialization.Encoding",
  100. format: "serialization.ParameterFormat",
  101. ) -> bytes:
  102. """
  103. Returns the parameters serialized as bytes.
  104. """
  105. @abc.abstractmethod
  106. def parameter_numbers(self) -> DHParameterNumbers:
  107. """
  108. Returns a DHParameterNumbers.
  109. """
  110. DHParametersWithSerialization = DHParameters
  111. class DHPublicKey(metaclass=abc.ABCMeta):
  112. @abc.abstractproperty
  113. def key_size(self) -> int:
  114. """
  115. The bit length of the prime modulus.
  116. """
  117. @abc.abstractmethod
  118. def parameters(self) -> DHParameters:
  119. """
  120. The DHParameters object associated with this public key.
  121. """
  122. @abc.abstractmethod
  123. def public_numbers(self) -> DHPublicNumbers:
  124. """
  125. Returns a DHPublicNumbers.
  126. """
  127. @abc.abstractmethod
  128. def public_bytes(
  129. self,
  130. encoding: "serialization.Encoding",
  131. format: "serialization.PublicFormat",
  132. ) -> bytes:
  133. """
  134. Returns the key serialized as bytes.
  135. """
  136. DHPublicKeyWithSerialization = DHPublicKey
  137. class DHPrivateKey(metaclass=abc.ABCMeta):
  138. @abc.abstractproperty
  139. def key_size(self) -> int:
  140. """
  141. The bit length of the prime modulus.
  142. """
  143. @abc.abstractmethod
  144. def public_key(self) -> DHPublicKey:
  145. """
  146. The DHPublicKey associated with this private key.
  147. """
  148. @abc.abstractmethod
  149. def parameters(self) -> DHParameters:
  150. """
  151. The DHParameters object associated with this private key.
  152. """
  153. @abc.abstractmethod
  154. def exchange(self, peer_public_key: DHPublicKey) -> bytes:
  155. """
  156. Given peer's DHPublicKey, carry out the key exchange and
  157. return shared key as bytes.
  158. """
  159. @abc.abstractmethod
  160. def private_numbers(self) -> DHPrivateNumbers:
  161. """
  162. Returns a DHPrivateNumbers.
  163. """
  164. @abc.abstractmethod
  165. def private_bytes(
  166. self,
  167. encoding: "serialization.Encoding",
  168. format: "serialization.PrivateFormat",
  169. encryption_algorithm: "serialization.KeySerializationEncryption",
  170. ) -> bytes:
  171. """
  172. Returns the key serialized as bytes.
  173. """
  174. DHPrivateKeyWithSerialization = DHPrivateKey