ML-KEM¶
ML-KEM (Module-Lattice-Based Key-Encapsulation Mechanism) is the post-quantum key encapsulation mechanism standardized by NIST in FIPS 203. It is derived from CRYSTALS-Kyber.
Its security is based on the hardness of the Module Learning With Errors problem (Module-LWE), which is believed to be hard even for quantum computers. Compared to ECC, keys and ciphertexts are much larger.
FIPS 203 defines three parameter sets:
Parameter set |
Constant |
NIST security category |
Public key |
Expanded private key |
Ciphertext |
|---|---|---|---|---|---|
ML-KEM-512 |
|
1 |
800 bytes |
1632 bytes |
768 bytes |
ML-KEM-768 |
|
3 |
1184 bytes |
2400 bytes |
1088 bytes |
ML-KEM-1024 |
|
5 |
1568 bytes |
3168 bytes |
1568 bytes |
Pass one of these constants as the param_set argument.
They are the members of the enum Crypto.PublicKey.MLKEM.ParamSet,
and the value of each member is the name of its parameter set (for instance, 'ML-KEM-768').
The shared secret is always 32 bytes long.
A private key can be represented in two ways:
the seed: the 64 random bytes the key is generated from (\(d \| z\) in FIPS 203). It is the most compact form.
the expanded private key: the decapsulation key defined in FIPS 203 (Algorithm 16). It cannot be converted back to the seed.
The names used in this module follow the specifications, but avoid dk on its own, because the specifications disagree on its meaning:
This module |
FIPS 203 |
|
|---|---|---|
|
\(d \| z\) |
|
|
|
|
|
|
|
With this module you can generate a new ML-KEM key:
>>> from Crypto.PublicKey import MLKEM
>>>
>>> key = MLKEM.generate(param_set=MLKEM.ML_KEM_768)
>>> seed = key.seed # 64 bytes, keep it secret
>>> ek = key.ek # 1184 bytes, the public key
and rebuild it later from its seed (or from the expanded private key), or get the public key:
>>> key = MLKEM.construct(param_set=MLKEM.ML_KEM_768, seed=seed)
>>> pub_key = MLKEM.construct(param_set=MLKEM.ML_KEM_768, ek=ek)
>>> pub_key == key.public_key()
True
construct() performs the input checks of FIPS 203:
the modulus check on a public key (Section 7.2)
and the hash check on an expanded private key (Section 7.3).
Currently, ML-KEM keys can only be used with HPKE
(Crypto.Protocol.HPKE), alone or combined with ECDH in a
hybrid KEM.
The implementation is based on mlkem-native.
ML-KEM keys (FIPS 203)
- class Crypto.PublicKey.MLKEM.MLKEMKey(*, param_set, seed=None, expanded_dk=None, ek=None)¶
Class defining an ML-KEM key (private or public). Do not instantiate directly. Use
generate()orconstruct()instead.- Variables:
param_set (
ParamSet) – The parameter set.
- Crypto.PublicKey.MLKEM.ML_KEM_1024 = ParamSet.ML_KEM_1024¶
Same as
ParamSet.ML_KEM_1024
- Crypto.PublicKey.MLKEM.ML_KEM_512 = ParamSet.ML_KEM_512¶
Same as
ParamSet.ML_KEM_512
- Crypto.PublicKey.MLKEM.ML_KEM_768 = ParamSet.ML_KEM_768¶
Same as
ParamSet.ML_KEM_768
- class Crypto.PublicKey.MLKEM.ParamSet(value)¶
The ML-KEM parameter sets (FIPS 203, Section 8). The value of each member is its name in FIPS 203.
- ML_KEM_1024 = 'ML-KEM-1024'¶
NIST security category 5
- ML_KEM_512 = 'ML-KEM-512'¶
NIST security category 1
- ML_KEM_768 = 'ML-KEM-768'¶
NIST security category 3
- Crypto.PublicKey.MLKEM.construct(*, param_set, seed=None, expanded_dk=None, ek=None)¶
Build an ML-KEM key (private or public) from its components.
- Parameters:
param_set (
ParamSet) – Mandatory. The parameter set, for instanceMLKEM.ML_KEM_768.seed (bytes) – The 64-byte seed of a private key: \(d \| z\) in FIPS 203 (the input of
ML-KEM.KeyGen_internal, Algorithm 16).expanded_dk (bytes) – The expanded decapsulation key (dk in FIPS 203). It must pass the hash check of FIPS 203 (Section 7.3).
ek (bytes) – The encapsulation key, that is, the public key (ek in FIPS 203). It must pass the modulus check of FIPS 203 (Section 7.2).
At least one of
seed,expanded_dkandekmust be present. If more than one is present, they must match, otherwiseValueErroris raised.- Returns:
a new ML-KEM key object
- Return type:
- Crypto.PublicKey.MLKEM.generate(*, param_set, randfunc=None)¶
Generate a new ML-KEM private key (FIPS 203, Algorithm 19).
- Parameters:
param_set (
ParamSet) – Mandatory. The parameter set, for instanceMLKEM.ML_KEM_768.randfunc (callable) – Optional. The RNG to read the 64-byte seed from. If
None,Crypto.Random.get_random_bytes()is used.
- Returns:
a new private key
- Return type: