dh.py 6.4 KB

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