mlkem.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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. from __future__ import annotations
  5. import abc
  6. from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
  7. from cryptography.hazmat.bindings._rust import openssl as rust_openssl
  8. from cryptography.hazmat.primitives import _serialization
  9. from cryptography.utils import Buffer
  10. class MLKEM768PublicKey(metaclass=abc.ABCMeta):
  11. @classmethod
  12. def from_public_bytes(cls, data: Buffer) -> MLKEM768PublicKey:
  13. from cryptography.hazmat.backends.openssl.backend import backend
  14. if not backend.mlkem_supported():
  15. raise UnsupportedAlgorithm(
  16. "ML-KEM-768 is not supported by this backend.",
  17. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  18. )
  19. return rust_openssl.mlkem.from_mlkem768_public_bytes(data)
  20. @abc.abstractmethod
  21. def encapsulate(self) -> tuple[bytes, bytes]:
  22. """
  23. Encapsulate: returns (shared_secret, ciphertext).
  24. """
  25. @abc.abstractmethod
  26. def public_bytes(
  27. self,
  28. encoding: _serialization.Encoding,
  29. format: _serialization.PublicFormat,
  30. ) -> bytes:
  31. """
  32. The serialized bytes of the public key.
  33. """
  34. @abc.abstractmethod
  35. def public_bytes_raw(self) -> bytes:
  36. """
  37. The raw bytes of the public key.
  38. Equivalent to public_bytes(Raw, Raw).
  39. The public key is 1,184 bytes for ML-KEM-768.
  40. """
  41. @abc.abstractmethod
  42. def __eq__(self, other: object) -> bool:
  43. """
  44. Checks equality.
  45. """
  46. @abc.abstractmethod
  47. def __copy__(self) -> MLKEM768PublicKey:
  48. """
  49. Returns a copy.
  50. """
  51. @abc.abstractmethod
  52. def __deepcopy__(self, memo: dict) -> MLKEM768PublicKey:
  53. """
  54. Returns a deep copy.
  55. """
  56. if hasattr(rust_openssl, "mlkem"):
  57. MLKEM768PublicKey.register(rust_openssl.mlkem.MLKEM768PublicKey)
  58. class MLKEM768PrivateKey(metaclass=abc.ABCMeta):
  59. @classmethod
  60. def generate(cls) -> MLKEM768PrivateKey:
  61. from cryptography.hazmat.backends.openssl.backend import backend
  62. if not backend.mlkem_supported():
  63. raise UnsupportedAlgorithm(
  64. "ML-KEM-768 is not supported by this backend.",
  65. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  66. )
  67. return rust_openssl.mlkem.generate_mlkem768_key()
  68. @classmethod
  69. def from_seed_bytes(cls, data: Buffer) -> MLKEM768PrivateKey:
  70. from cryptography.hazmat.backends.openssl.backend import backend
  71. if not backend.mlkem_supported():
  72. raise UnsupportedAlgorithm(
  73. "ML-KEM-768 is not supported by this backend.",
  74. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  75. )
  76. return rust_openssl.mlkem.from_mlkem768_seed_bytes(data)
  77. @abc.abstractmethod
  78. def decapsulate(self, ciphertext: Buffer) -> bytes:
  79. """
  80. Decapsulate: returns shared_secret.
  81. """
  82. @abc.abstractmethod
  83. def public_key(self) -> MLKEM768PublicKey:
  84. """
  85. The MLKEM768PublicKey derived from this private key.
  86. """
  87. @abc.abstractmethod
  88. def private_bytes(
  89. self,
  90. encoding: _serialization.Encoding,
  91. format: _serialization.PrivateFormat,
  92. encryption_algorithm: _serialization.KeySerializationEncryption,
  93. ) -> bytes:
  94. """
  95. The serialized bytes of the private key.
  96. """
  97. @abc.abstractmethod
  98. def private_bytes_raw(self) -> bytes:
  99. """
  100. The raw bytes of the private key (64-byte seed).
  101. Equivalent to private_bytes(Raw, Raw, NoEncryption()).
  102. """
  103. @abc.abstractmethod
  104. def __copy__(self) -> MLKEM768PrivateKey:
  105. """
  106. Returns a copy.
  107. """
  108. @abc.abstractmethod
  109. def __deepcopy__(self, memo: dict) -> MLKEM768PrivateKey:
  110. """
  111. Returns a deep copy.
  112. """
  113. if hasattr(rust_openssl, "mlkem"):
  114. MLKEM768PrivateKey.register(rust_openssl.mlkem.MLKEM768PrivateKey)
  115. class MLKEM1024PublicKey(metaclass=abc.ABCMeta):
  116. @classmethod
  117. def from_public_bytes(cls, data: Buffer) -> MLKEM1024PublicKey:
  118. from cryptography.hazmat.backends.openssl.backend import backend
  119. if not backend.mlkem_supported():
  120. raise UnsupportedAlgorithm(
  121. "ML-KEM-1024 is not supported by this backend.",
  122. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  123. )
  124. return rust_openssl.mlkem.from_mlkem1024_public_bytes(data)
  125. @abc.abstractmethod
  126. def encapsulate(self) -> tuple[bytes, bytes]:
  127. """
  128. Encapsulate: returns (shared_secret, ciphertext).
  129. """
  130. @abc.abstractmethod
  131. def public_bytes(
  132. self,
  133. encoding: _serialization.Encoding,
  134. format: _serialization.PublicFormat,
  135. ) -> bytes:
  136. """
  137. The serialized bytes of the public key.
  138. """
  139. @abc.abstractmethod
  140. def public_bytes_raw(self) -> bytes:
  141. """
  142. The raw bytes of the public key.
  143. Equivalent to public_bytes(Raw, Raw).
  144. The public key is 1,568 bytes for ML-KEM-1024.
  145. """
  146. @abc.abstractmethod
  147. def __eq__(self, other: object) -> bool:
  148. """
  149. Checks equality.
  150. """
  151. @abc.abstractmethod
  152. def __copy__(self) -> MLKEM1024PublicKey:
  153. """
  154. Returns a copy.
  155. """
  156. @abc.abstractmethod
  157. def __deepcopy__(self, memo: dict) -> MLKEM1024PublicKey:
  158. """
  159. Returns a deep copy.
  160. """
  161. if hasattr(rust_openssl, "mlkem"):
  162. MLKEM1024PublicKey.register(rust_openssl.mlkem.MLKEM1024PublicKey)
  163. class MLKEM1024PrivateKey(metaclass=abc.ABCMeta):
  164. @classmethod
  165. def generate(cls) -> MLKEM1024PrivateKey:
  166. from cryptography.hazmat.backends.openssl.backend import backend
  167. if not backend.mlkem_supported():
  168. raise UnsupportedAlgorithm(
  169. "ML-KEM-1024 is not supported by this backend.",
  170. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  171. )
  172. return rust_openssl.mlkem.generate_mlkem1024_key()
  173. @classmethod
  174. def from_seed_bytes(cls, data: Buffer) -> MLKEM1024PrivateKey:
  175. from cryptography.hazmat.backends.openssl.backend import backend
  176. if not backend.mlkem_supported():
  177. raise UnsupportedAlgorithm(
  178. "ML-KEM-1024 is not supported by this backend.",
  179. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  180. )
  181. return rust_openssl.mlkem.from_mlkem1024_seed_bytes(data)
  182. @abc.abstractmethod
  183. def decapsulate(self, ciphertext: Buffer) -> bytes:
  184. """
  185. Decapsulate: returns shared_secret.
  186. """
  187. @abc.abstractmethod
  188. def public_key(self) -> MLKEM1024PublicKey:
  189. """
  190. The MLKEM1024PublicKey derived from this private key.
  191. """
  192. @abc.abstractmethod
  193. def private_bytes(
  194. self,
  195. encoding: _serialization.Encoding,
  196. format: _serialization.PrivateFormat,
  197. encryption_algorithm: _serialization.KeySerializationEncryption,
  198. ) -> bytes:
  199. """
  200. The serialized bytes of the private key.
  201. """
  202. @abc.abstractmethod
  203. def private_bytes_raw(self) -> bytes:
  204. """
  205. The raw bytes of the private key (64-byte seed).
  206. Equivalent to private_bytes(Raw, Raw, NoEncryption()).
  207. """
  208. @abc.abstractmethod
  209. def __copy__(self) -> MLKEM1024PrivateKey:
  210. """
  211. Returns a copy.
  212. """
  213. @abc.abstractmethod
  214. def __deepcopy__(self, memo: dict) -> MLKEM1024PrivateKey:
  215. """
  216. Returns a deep copy.
  217. """
  218. if hasattr(rust_openssl, "mlkem"):
  219. MLKEM1024PrivateKey.register(rust_openssl.mlkem.MLKEM1024PrivateKey)