Skip to content

Commit fc9e0d5

Browse files
authored
Add documentation for MLKEM (#14674)
* Add documentation for MLKEM * Add words
1 parent 8b7ecd2 commit fc9e0d5

3 files changed

Lines changed: 375 additions & 1 deletion

File tree

docs/hazmat/primitives/asymmetric/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ private key is able to decrypt it.
2424
:maxdepth: 1
2525

2626
mldsa
27+
mlkem
2728
ed25519
2829
x25519
2930
ed448
Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
.. hazmat::
2+
3+
ML-KEM key encapsulation
4+
========================
5+
6+
.. currentmodule:: cryptography.hazmat.primitives.asymmetric.mlkem
7+
8+
ML-KEM is a post-quantum key encapsulation mechanism based on module
9+
lattices, standardized in `FIPS 203`_.
10+
11+
Encapsulation & Decapsulation
12+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13+
14+
.. doctest::
15+
:skipif: not _backend.mlkem_supported()
16+
17+
>>> from cryptography.hazmat.primitives.asymmetric.mlkem import MLKEM768PrivateKey
18+
>>> private_key = MLKEM768PrivateKey.generate()
19+
>>> public_key = private_key.public_key()
20+
>>> shared_secret, ciphertext = public_key.encapsulate()
21+
>>> recovered_secret = private_key.decapsulate(ciphertext)
22+
>>> shared_secret == recovered_secret
23+
True
24+
25+
Key interfaces
26+
~~~~~~~~~~~~~~
27+
28+
.. class:: MLKEM768PrivateKey
29+
30+
.. versionadded:: 47.0
31+
32+
.. classmethod:: generate()
33+
34+
Generate an ML-KEM-768 private key.
35+
36+
:returns: :class:`MLKEM768PrivateKey`
37+
38+
:raises cryptography.exceptions.UnsupportedAlgorithm: If ML-KEM-768 is
39+
not supported by the backend ``cryptography`` is using.
40+
41+
.. classmethod:: from_seed_bytes(data)
42+
43+
Load an ML-KEM-768 private key from seed bytes.
44+
45+
:param data: 64 byte seed.
46+
:type data: :term:`bytes-like`
47+
48+
:returns: :class:`MLKEM768PrivateKey`
49+
50+
:raises ValueError: If the seed is not 64 bytes.
51+
52+
:raises cryptography.exceptions.UnsupportedAlgorithm: If ML-KEM-768 is
53+
not supported by the backend ``cryptography`` is using.
54+
55+
.. doctest::
56+
:skipif: not _backend.mlkem_supported()
57+
58+
>>> from cryptography.hazmat.primitives.asymmetric import mlkem
59+
>>> private_key = mlkem.MLKEM768PrivateKey.generate()
60+
>>> seed = private_key.private_bytes_raw()
61+
>>> same_key = mlkem.MLKEM768PrivateKey.from_seed_bytes(seed)
62+
63+
.. method:: public_key()
64+
65+
:returns: :class:`MLKEM768PublicKey`
66+
67+
.. method:: decapsulate(ciphertext)
68+
69+
Decapsulate a ciphertext using ML-KEM-768, returning the shared
70+
secret.
71+
72+
:param ciphertext: The ciphertext to decapsulate (1088 bytes).
73+
:type ciphertext: :term:`bytes-like`
74+
75+
:returns bytes: The shared secret (32 bytes).
76+
77+
:raises ValueError: If the ciphertext is not the correct length.
78+
79+
.. method:: private_bytes(encoding, format, encryption_algorithm)
80+
81+
Allows serialization of the key to bytes. Encoding (
82+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
83+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
84+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
85+
format (
86+
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`
87+
or
88+
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
89+
) are chosen to define the exact serialization.
90+
91+
This method only returns the serialization of the seed form of the
92+
private key, never the expanded one.
93+
94+
:param encoding: A value from the
95+
:class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
96+
97+
:param format: A value from the
98+
:class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
99+
enum. If the ``encoding`` is
100+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
101+
then ``format`` must be
102+
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
103+
, otherwise it must be
104+
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`.
105+
106+
:param encryption_algorithm: An instance of an object conforming to the
107+
:class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
108+
interface.
109+
110+
:return bytes: Serialized key.
111+
112+
.. method:: private_bytes_raw()
113+
114+
Allows serialization of the key to raw bytes. This method is a
115+
convenience shortcut for calling :meth:`private_bytes` with
116+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
117+
encoding,
118+
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
119+
format, and
120+
:class:`~cryptography.hazmat.primitives.serialization.NoEncryption`.
121+
122+
This method only returns the seed form of the private key (64 bytes).
123+
124+
:return bytes: Raw key (64-byte seed).
125+
126+
.. class:: MLKEM768PublicKey
127+
128+
.. versionadded:: 47.0
129+
130+
.. classmethod:: from_public_bytes(data)
131+
132+
:param bytes data: 1184 byte public key.
133+
134+
:returns: :class:`MLKEM768PublicKey`
135+
136+
:raises ValueError: If the public key is not 1184 bytes.
137+
138+
:raises cryptography.exceptions.UnsupportedAlgorithm: If ML-KEM-768 is
139+
not supported by the backend ``cryptography`` is using.
140+
141+
.. doctest::
142+
:skipif: not _backend.mlkem_supported()
143+
144+
>>> from cryptography.hazmat.primitives import serialization
145+
>>> from cryptography.hazmat.primitives.asymmetric import mlkem
146+
>>> private_key = mlkem.MLKEM768PrivateKey.generate()
147+
>>> public_key = private_key.public_key()
148+
>>> public_bytes = public_key.public_bytes(
149+
... encoding=serialization.Encoding.Raw,
150+
... format=serialization.PublicFormat.Raw
151+
... )
152+
>>> loaded_public_key = mlkem.MLKEM768PublicKey.from_public_bytes(public_bytes)
153+
154+
.. method:: encapsulate()
155+
156+
Generate a shared secret and encapsulate it for this public key.
157+
158+
:returns: A ``(shared_secret, ciphertext)`` tuple where both values
159+
are :class:`bytes`. The shared secret is 32 bytes and the
160+
ciphertext is 1088 bytes.
161+
162+
.. method:: public_bytes(encoding, format)
163+
164+
Allows serialization of the key to bytes. Encoding (
165+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
166+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
167+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
168+
format (
169+
:attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`
170+
or
171+
:attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
172+
) are chosen to define the exact serialization.
173+
174+
:param encoding: A value from the
175+
:class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
176+
177+
:param format: A value from the
178+
:class:`~cryptography.hazmat.primitives.serialization.PublicFormat`
179+
enum. If the ``encoding`` is
180+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
181+
then ``format`` must be
182+
:attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
183+
, otherwise it must be
184+
:attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
185+
186+
:returns bytes: The public key bytes.
187+
188+
.. method:: public_bytes_raw()
189+
190+
Allows serialization of the key to raw bytes. This method is a
191+
convenience shortcut for calling :meth:`public_bytes` with
192+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
193+
encoding and
194+
:attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
195+
format.
196+
197+
:return bytes: 1184-byte raw public key.
198+
199+
.. class:: MLKEM1024PrivateKey
200+
201+
.. versionadded:: 47.0
202+
203+
.. classmethod:: generate()
204+
205+
Generate an ML-KEM-1024 private key.
206+
207+
:returns: :class:`MLKEM1024PrivateKey`
208+
209+
:raises cryptography.exceptions.UnsupportedAlgorithm: If ML-KEM-1024 is
210+
not supported by the backend ``cryptography`` is using.
211+
212+
.. classmethod:: from_seed_bytes(data)
213+
214+
Load an ML-KEM-1024 private key from seed bytes.
215+
216+
:param data: 64 byte seed.
217+
:type data: :term:`bytes-like`
218+
219+
:returns: :class:`MLKEM1024PrivateKey`
220+
221+
:raises ValueError: If the seed is not 64 bytes.
222+
223+
:raises cryptography.exceptions.UnsupportedAlgorithm: If ML-KEM-1024 is
224+
not supported by the backend ``cryptography`` is using.
225+
226+
.. doctest::
227+
:skipif: not _backend.mlkem_supported()
228+
229+
>>> from cryptography.hazmat.primitives.asymmetric import mlkem
230+
>>> private_key = mlkem.MLKEM1024PrivateKey.generate()
231+
>>> seed = private_key.private_bytes_raw()
232+
>>> same_key = mlkem.MLKEM1024PrivateKey.from_seed_bytes(seed)
233+
234+
.. method:: public_key()
235+
236+
:returns: :class:`MLKEM1024PublicKey`
237+
238+
.. method:: decapsulate(ciphertext)
239+
240+
Decapsulate a ciphertext using ML-KEM-1024, returning the shared
241+
secret.
242+
243+
:param ciphertext: The ciphertext to decapsulate (1568 bytes).
244+
:type ciphertext: :term:`bytes-like`
245+
246+
:returns bytes: The shared secret (32 bytes).
247+
248+
:raises ValueError: If the ciphertext is not the correct length.
249+
250+
.. method:: private_bytes(encoding, format, encryption_algorithm)
251+
252+
Allows serialization of the key to bytes. Encoding (
253+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
254+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
255+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
256+
format (
257+
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`
258+
or
259+
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
260+
) are chosen to define the exact serialization.
261+
262+
This method only returns the serialization of the seed form of the
263+
private key, never the expanded one.
264+
265+
:param encoding: A value from the
266+
:class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
267+
268+
:param format: A value from the
269+
:class:`~cryptography.hazmat.primitives.serialization.PrivateFormat`
270+
enum. If the ``encoding`` is
271+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
272+
then ``format`` must be
273+
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
274+
, otherwise it must be
275+
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.PKCS8`.
276+
277+
:param encryption_algorithm: An instance of an object conforming to the
278+
:class:`~cryptography.hazmat.primitives.serialization.KeySerializationEncryption`
279+
interface.
280+
281+
:return bytes: Serialized key.
282+
283+
.. method:: private_bytes_raw()
284+
285+
Allows serialization of the key to raw bytes. This method is a
286+
convenience shortcut for calling :meth:`private_bytes` with
287+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
288+
encoding,
289+
:attr:`~cryptography.hazmat.primitives.serialization.PrivateFormat.Raw`
290+
format, and
291+
:class:`~cryptography.hazmat.primitives.serialization.NoEncryption`.
292+
293+
This method only returns the seed form of the private key (64 bytes).
294+
295+
:return bytes: Raw key (64-byte seed).
296+
297+
.. class:: MLKEM1024PublicKey
298+
299+
.. versionadded:: 47.0
300+
301+
.. classmethod:: from_public_bytes(data)
302+
303+
:param bytes data: 1568 byte public key.
304+
305+
:returns: :class:`MLKEM1024PublicKey`
306+
307+
:raises ValueError: If the public key is not 1568 bytes.
308+
309+
:raises cryptography.exceptions.UnsupportedAlgorithm: If ML-KEM-1024 is
310+
not supported by the backend ``cryptography`` is using.
311+
312+
.. doctest::
313+
:skipif: not _backend.mlkem_supported()
314+
315+
>>> from cryptography.hazmat.primitives import serialization
316+
>>> from cryptography.hazmat.primitives.asymmetric import mlkem
317+
>>> private_key = mlkem.MLKEM1024PrivateKey.generate()
318+
>>> public_key = private_key.public_key()
319+
>>> public_bytes = public_key.public_bytes(
320+
... encoding=serialization.Encoding.Raw,
321+
... format=serialization.PublicFormat.Raw
322+
... )
323+
>>> loaded_public_key = mlkem.MLKEM1024PublicKey.from_public_bytes(public_bytes)
324+
325+
.. method:: encapsulate()
326+
327+
Generate a shared secret and encapsulate it for this public key.
328+
329+
:returns: A ``(shared_secret, ciphertext)`` tuple where both values
330+
are :class:`bytes`. The shared secret is 32 bytes and the
331+
ciphertext is 1568 bytes.
332+
333+
.. method:: public_bytes(encoding, format)
334+
335+
Allows serialization of the key to bytes. Encoding (
336+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.PEM`,
337+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.DER`, or
338+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`) and
339+
format (
340+
:attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`
341+
or
342+
:attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
343+
) are chosen to define the exact serialization.
344+
345+
:param encoding: A value from the
346+
:class:`~cryptography.hazmat.primitives.serialization.Encoding` enum.
347+
348+
:param format: A value from the
349+
:class:`~cryptography.hazmat.primitives.serialization.PublicFormat`
350+
enum. If the ``encoding`` is
351+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
352+
then ``format`` must be
353+
:attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
354+
, otherwise it must be
355+
:attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.SubjectPublicKeyInfo`.
356+
357+
:returns bytes: The public key bytes.
358+
359+
.. method:: public_bytes_raw()
360+
361+
Allows serialization of the key to raw bytes. This method is a
362+
convenience shortcut for calling :meth:`public_bytes` with
363+
:attr:`~cryptography.hazmat.primitives.serialization.Encoding.Raw`
364+
encoding and
365+
:attr:`~cryptography.hazmat.primitives.serialization.PublicFormat.Raw`
366+
format.
367+
368+
:return bytes: 1568-byte raw public key.
369+
370+
371+
.. _`FIPS 203`: https://csrc.nist.gov/pubs/fips/203/final

docs/spelling_wordlist.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ cryptographically
3636
de
3737
Debian
3838
deallocated
39+
decapsulate
40+
Decapsulate
41+
Decapsulation
3942
declaratively
4043
decrypt
4144
decrypts
@@ -50,7 +53,6 @@ deserialized
5053
Deserialization
5154
deserializing
5255
Diffie
53-
Diffie
5456
disambiguating
5557
Django
5658
Docstrings

0 commit comments

Comments
 (0)