mldsa.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  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 MLDSA44PublicKey(metaclass=abc.ABCMeta):
  11. @classmethod
  12. def from_public_bytes(cls, data: bytes) -> MLDSA44PublicKey:
  13. from cryptography.hazmat.backends.openssl.backend import backend
  14. if not backend.mldsa_supported():
  15. raise UnsupportedAlgorithm(
  16. "ML-DSA-44 is not supported by this backend.",
  17. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  18. )
  19. return rust_openssl.mldsa.from_mldsa44_public_bytes(data)
  20. @abc.abstractmethod
  21. def public_bytes(
  22. self,
  23. encoding: _serialization.Encoding,
  24. format: _serialization.PublicFormat,
  25. ) -> bytes:
  26. """
  27. The serialized bytes of the public key.
  28. """
  29. @abc.abstractmethod
  30. def public_bytes_raw(self) -> bytes:
  31. """
  32. The raw bytes of the public key.
  33. Equivalent to public_bytes(Raw, Raw).
  34. The public key is 1,312 bytes for MLDSA-44.
  35. """
  36. @abc.abstractmethod
  37. def verify(
  38. self,
  39. signature: Buffer,
  40. data: Buffer,
  41. context: Buffer | None = None,
  42. ) -> None:
  43. """
  44. Verify the signature.
  45. """
  46. @abc.abstractmethod
  47. def __eq__(self, other: object) -> bool:
  48. """
  49. Checks equality.
  50. """
  51. @abc.abstractmethod
  52. def __copy__(self) -> MLDSA44PublicKey:
  53. """
  54. Returns a copy.
  55. """
  56. @abc.abstractmethod
  57. def __deepcopy__(self, memo: dict) -> MLDSA44PublicKey:
  58. """
  59. Returns a deep copy.
  60. """
  61. if hasattr(rust_openssl, "mldsa"):
  62. MLDSA44PublicKey.register(rust_openssl.mldsa.MLDSA44PublicKey)
  63. class MLDSA44PrivateKey(metaclass=abc.ABCMeta):
  64. @classmethod
  65. def generate(cls) -> MLDSA44PrivateKey:
  66. from cryptography.hazmat.backends.openssl.backend import backend
  67. if not backend.mldsa_supported():
  68. raise UnsupportedAlgorithm(
  69. "ML-DSA-44 is not supported by this backend.",
  70. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  71. )
  72. return rust_openssl.mldsa.generate_mldsa44_key()
  73. @classmethod
  74. def from_seed_bytes(cls, data: Buffer) -> MLDSA44PrivateKey:
  75. from cryptography.hazmat.backends.openssl.backend import backend
  76. if not backend.mldsa_supported():
  77. raise UnsupportedAlgorithm(
  78. "ML-DSA-44 is not supported by this backend.",
  79. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  80. )
  81. return rust_openssl.mldsa.from_mldsa44_seed_bytes(data)
  82. @abc.abstractmethod
  83. def public_key(self) -> MLDSA44PublicKey:
  84. """
  85. The MLDSA44PublicKey derived from the 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. This method only returns the serialization of the seed form of the
  97. private key, never the expanded one.
  98. """
  99. @abc.abstractmethod
  100. def private_bytes_raw(self) -> bytes:
  101. """
  102. The raw bytes of the private key.
  103. Equivalent to private_bytes(Raw, Raw, NoEncryption()).
  104. This method only returns the seed form of the private key (32 bytes).
  105. """
  106. @abc.abstractmethod
  107. def sign(self, data: Buffer, context: Buffer | None = None) -> bytes:
  108. """
  109. Signs the data.
  110. """
  111. @abc.abstractmethod
  112. def __copy__(self) -> MLDSA44PrivateKey:
  113. """
  114. Returns a copy.
  115. """
  116. @abc.abstractmethod
  117. def __deepcopy__(self, memo: dict) -> MLDSA44PrivateKey:
  118. """
  119. Returns a deep copy.
  120. """
  121. if hasattr(rust_openssl, "mldsa"):
  122. MLDSA44PrivateKey.register(rust_openssl.mldsa.MLDSA44PrivateKey)
  123. class MLDSA65PublicKey(metaclass=abc.ABCMeta):
  124. @classmethod
  125. def from_public_bytes(cls, data: bytes) -> MLDSA65PublicKey:
  126. from cryptography.hazmat.backends.openssl.backend import backend
  127. if not backend.mldsa_supported():
  128. raise UnsupportedAlgorithm(
  129. "ML-DSA-65 is not supported by this backend.",
  130. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  131. )
  132. return rust_openssl.mldsa.from_mldsa65_public_bytes(data)
  133. @abc.abstractmethod
  134. def public_bytes(
  135. self,
  136. encoding: _serialization.Encoding,
  137. format: _serialization.PublicFormat,
  138. ) -> bytes:
  139. """
  140. The serialized bytes of the public key.
  141. """
  142. @abc.abstractmethod
  143. def public_bytes_raw(self) -> bytes:
  144. """
  145. The raw bytes of the public key.
  146. Equivalent to public_bytes(Raw, Raw).
  147. The public key is 1,952 bytes for MLDSA-65.
  148. """
  149. @abc.abstractmethod
  150. def verify(
  151. self,
  152. signature: Buffer,
  153. data: Buffer,
  154. context: Buffer | None = None,
  155. ) -> None:
  156. """
  157. Verify the signature.
  158. """
  159. @abc.abstractmethod
  160. def __eq__(self, other: object) -> bool:
  161. """
  162. Checks equality.
  163. """
  164. @abc.abstractmethod
  165. def __copy__(self) -> MLDSA65PublicKey:
  166. """
  167. Returns a copy.
  168. """
  169. @abc.abstractmethod
  170. def __deepcopy__(self, memo: dict) -> MLDSA65PublicKey:
  171. """
  172. Returns a deep copy.
  173. """
  174. if hasattr(rust_openssl, "mldsa"):
  175. MLDSA65PublicKey.register(rust_openssl.mldsa.MLDSA65PublicKey)
  176. class MLDSA65PrivateKey(metaclass=abc.ABCMeta):
  177. @classmethod
  178. def generate(cls) -> MLDSA65PrivateKey:
  179. from cryptography.hazmat.backends.openssl.backend import backend
  180. if not backend.mldsa_supported():
  181. raise UnsupportedAlgorithm(
  182. "ML-DSA-65 is not supported by this backend.",
  183. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  184. )
  185. return rust_openssl.mldsa.generate_mldsa65_key()
  186. @classmethod
  187. def from_seed_bytes(cls, data: Buffer) -> MLDSA65PrivateKey:
  188. from cryptography.hazmat.backends.openssl.backend import backend
  189. if not backend.mldsa_supported():
  190. raise UnsupportedAlgorithm(
  191. "ML-DSA-65 is not supported by this backend.",
  192. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  193. )
  194. return rust_openssl.mldsa.from_mldsa65_seed_bytes(data)
  195. @abc.abstractmethod
  196. def public_key(self) -> MLDSA65PublicKey:
  197. """
  198. The MLDSA65PublicKey derived from the private key.
  199. """
  200. @abc.abstractmethod
  201. def private_bytes(
  202. self,
  203. encoding: _serialization.Encoding,
  204. format: _serialization.PrivateFormat,
  205. encryption_algorithm: _serialization.KeySerializationEncryption,
  206. ) -> bytes:
  207. """
  208. The serialized bytes of the private key.
  209. This method only returns the serialization of the seed form of the
  210. private key, never the expanded one.
  211. """
  212. @abc.abstractmethod
  213. def private_bytes_raw(self) -> bytes:
  214. """
  215. The raw bytes of the private key.
  216. Equivalent to private_bytes(Raw, Raw, NoEncryption()).
  217. This method only returns the seed form of the private key (32 bytes).
  218. """
  219. @abc.abstractmethod
  220. def sign(self, data: Buffer, context: Buffer | None = None) -> bytes:
  221. """
  222. Signs the data.
  223. """
  224. @abc.abstractmethod
  225. def __copy__(self) -> MLDSA65PrivateKey:
  226. """
  227. Returns a copy.
  228. """
  229. @abc.abstractmethod
  230. def __deepcopy__(self, memo: dict) -> MLDSA65PrivateKey:
  231. """
  232. Returns a deep copy.
  233. """
  234. if hasattr(rust_openssl, "mldsa"):
  235. MLDSA65PrivateKey.register(rust_openssl.mldsa.MLDSA65PrivateKey)
  236. class MLDSA87PublicKey(metaclass=abc.ABCMeta):
  237. @classmethod
  238. def from_public_bytes(cls, data: bytes) -> MLDSA87PublicKey:
  239. from cryptography.hazmat.backends.openssl.backend import backend
  240. if not backend.mldsa_supported():
  241. raise UnsupportedAlgorithm(
  242. "ML-DSA-87 is not supported by this backend.",
  243. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  244. )
  245. return rust_openssl.mldsa.from_mldsa87_public_bytes(data)
  246. @abc.abstractmethod
  247. def public_bytes(
  248. self,
  249. encoding: _serialization.Encoding,
  250. format: _serialization.PublicFormat,
  251. ) -> bytes:
  252. """
  253. The serialized bytes of the public key.
  254. """
  255. @abc.abstractmethod
  256. def public_bytes_raw(self) -> bytes:
  257. """
  258. The raw bytes of the public key.
  259. Equivalent to public_bytes(Raw, Raw).
  260. The public key is 2,592 bytes for MLDSA-87.
  261. """
  262. @abc.abstractmethod
  263. def verify(
  264. self,
  265. signature: Buffer,
  266. data: Buffer,
  267. context: Buffer | None = None,
  268. ) -> None:
  269. """
  270. Verify the signature.
  271. """
  272. @abc.abstractmethod
  273. def __eq__(self, other: object) -> bool:
  274. """
  275. Checks equality.
  276. """
  277. @abc.abstractmethod
  278. def __copy__(self) -> MLDSA87PublicKey:
  279. """
  280. Returns a copy.
  281. """
  282. @abc.abstractmethod
  283. def __deepcopy__(self, memo: dict) -> MLDSA87PublicKey:
  284. """
  285. Returns a deep copy.
  286. """
  287. if hasattr(rust_openssl, "mldsa"):
  288. MLDSA87PublicKey.register(rust_openssl.mldsa.MLDSA87PublicKey)
  289. class MLDSA87PrivateKey(metaclass=abc.ABCMeta):
  290. @classmethod
  291. def generate(cls) -> MLDSA87PrivateKey:
  292. from cryptography.hazmat.backends.openssl.backend import backend
  293. if not backend.mldsa_supported():
  294. raise UnsupportedAlgorithm(
  295. "ML-DSA-87 is not supported by this backend.",
  296. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  297. )
  298. return rust_openssl.mldsa.generate_mldsa87_key()
  299. @classmethod
  300. def from_seed_bytes(cls, data: Buffer) -> MLDSA87PrivateKey:
  301. from cryptography.hazmat.backends.openssl.backend import backend
  302. if not backend.mldsa_supported():
  303. raise UnsupportedAlgorithm(
  304. "ML-DSA-87 is not supported by this backend.",
  305. _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM,
  306. )
  307. return rust_openssl.mldsa.from_mldsa87_seed_bytes(data)
  308. @abc.abstractmethod
  309. def public_key(self) -> MLDSA87PublicKey:
  310. """
  311. The MLDSA87PublicKey derived from the private key.
  312. """
  313. @abc.abstractmethod
  314. def private_bytes(
  315. self,
  316. encoding: _serialization.Encoding,
  317. format: _serialization.PrivateFormat,
  318. encryption_algorithm: _serialization.KeySerializationEncryption,
  319. ) -> bytes:
  320. """
  321. The serialized bytes of the private key.
  322. This method only returns the serialization of the seed form of the
  323. private key, never the expanded one.
  324. """
  325. @abc.abstractmethod
  326. def private_bytes_raw(self) -> bytes:
  327. """
  328. The raw bytes of the private key.
  329. Equivalent to private_bytes(Raw, Raw, NoEncryption()).
  330. This method only returns the seed form of the private key (32 bytes).
  331. """
  332. @abc.abstractmethod
  333. def sign(self, data: Buffer, context: Buffer | None = None) -> bytes:
  334. """
  335. Signs the data.
  336. """
  337. @abc.abstractmethod
  338. def __copy__(self) -> MLDSA87PrivateKey:
  339. """
  340. Returns a copy.
  341. """
  342. @abc.abstractmethod
  343. def __deepcopy__(self, memo: dict) -> MLDSA87PrivateKey:
  344. """
  345. Returns a deep copy.
  346. """
  347. if hasattr(rust_openssl, "mldsa"):
  348. MLDSA87PrivateKey.register(rust_openssl.mldsa.MLDSA87PrivateKey)