silk.crypto.ml_kem.
Agree on a shared secret with ML-KEM (FIPS 203), the module-lattice key encapsulation mechanism, at the levels ML-KEM-512, ML-KEM-768, and ML-KEM-1024.
When to use#
Use MlKem when a shared secret must stay secret also against an attacker with a large
quantum computer, for example in a hybrid TLS 1.3 group such as X25519MLKEM768. One side makes
a key pair with MlKem.keyPairFromSeed and sends the encapsulation key. The other side calls
MlKem.encapsulate, keeps the 32-byte shared secret, and sends the ciphertext back. The first
side gets the same secret with MlKem.decapsulate. Use silk.crypto.ml_key to read and write
the keys in PKCS #8 and SubjectPublicKeyInfo.
Details#
The caller gives every buffer, so nothing allocates. A key pair comes from a 64-byte seed
d || z, the form that PKCS #8 stores; the functions of MlKemParameters give the sizes.
Decapsulation runs in constant time for the secret values and returns the implicit-rejection
secret for a ciphertext that does not match, as FIPS 203 says, so it never fails for a
ciphertext of the right length. The NTT uses 16-bit Montgomery products with lazy reduction.
The encapsulation and decapsulation keys are checked as FIPS 203 section 7 asks.
Errors#
MlKemErrorfor a buffer of the wrong length, or for a key that fails the checks of FIPS 203.
Gotchas#
ML-KEM does not tell you who the other side is; authenticate the exchange, for example with a signature. Secrets are not erased.
Examples#
Agree on a secret#
import silk.core.result { Result }
import silk.crypto.ml_kem { MlKem, MlKemError, MlKemParameters }
pub fn main() -> i32 {
let parameters = MlKemParameters.MlKem768
// Real programs fill the seed and the message from a secure `Random` provider.
let seed: [u8; 64] = [1; 64]
let mut encapsulationKey: [u8; 1184] = [0; 1184]
let mut decapsulationKey: [u8; 2400] = [0; 2400]
match MlKem.keyPairFromSeed(parameters, &seed, &mut encapsulationKey, &mut decapsulationKey) {
Result<(), MlKemError>.Success { .. } => {}
Result<(), MlKemError>.Failure { error: _ } => {
return 1
}
}
let message: [u8; 32] = [2; 32]
let mut ciphertext: [u8; 1088] = [0; 1088]
let sent = match MlKem.encapsulateWith(parameters, &encapsulationKey, &message, &mut ciphertext) {
Result<[u8; 32], MlKemError>.Success { value } => value
Result<[u8; 32], MlKemError>.Failure { error: _ } => {
return 1
}
}
let received = match MlKem.decapsulate(parameters, &decapsulationKey, &ciphertext) {
Result<[u8; 32], MlKemError>.Success { value } => value
Result<[u8; 32], MlKemError>.Failure { error: _ } => {
return 1
}
}
if sent[0] != received[0] || sent[31] != received[31] {
return 1
}
return 0
}Import as MlKem with import silk.crypto.ml_kem { MlKem }.
Public declarations: 3.
MlKemParameters#
pub enum MlKemParametersA parameter set of FIPS 203.
MlKem512#
MlKem512ML-KEM-512, security category 1.
MlKem768#
MlKem768ML-KEM-768, security category 3.
MlKem1024#
MlKem1024ML-KEM-1024, security category 5.
Implementation MlKemParameters#
impl MlKemParametersMethod encapsulationKeyLength#
pub fn encapsulationKeyLength(self: &Self) -> usizeReturns the length of an encapsulation key in bytes: 800, 1184, or 1568.
Method decapsulationKeyLength#
pub fn decapsulationKeyLength(self: &Self) -> usizeReturns the length of a decapsulation key in bytes: 1632, 2400, or 3168.
Method ciphertextLength#
pub fn ciphertextLength(self: &Self) -> usizeReturns the length of a ciphertext in bytes: 768, 1088, or 1568.
Method objectIdentifier#
pub fn objectIdentifier(self: &Self) -> &[u8]Returns the content bytes of the object identifier that names the parameter set, without the
tag and length: id-alg-ml-kem-512 is 2.16.840.1.101.3.4.4.1, and the others end in 2 and 3.
Implementation Debug for MlKemParameters#
impl Debug for MlKemParametersOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the name of the variant, such as MlKem768.
MlKemError#
pub enum MlKemErrorThe reason that an ML-KEM call failed. It holds no secret bytes.
InvalidLength#
InvalidLengthA seed, key, message, ciphertext, or output buffer does not have the length of the parameter set.
InvalidEncapsulationKey#
InvalidEncapsulationKeyThe encapsulation key fails the modulus check of FIPS 203 section 7.2: a coefficient is not below q.
InvalidDecapsulationKey#
InvalidDecapsulationKeyThe decapsulation key fails the hash check of FIPS 203 section 7.3: it does not hold the hash of its encapsulation key.
Implementation Debug for MlKemError#
impl Debug for MlKemErrorOperation debug#
effect fn debug(self: &Self, formatter: &mut Formatter) -> () ! WriterError ? &mut WriterWrites the name of the variant, such as InvalidLength.
MlKem#
pub struct MlKemThe functions of ML-KEM.
When to use#
Make a key pair with MlKem.keyPairFromSeed, encapsulate with MlKem.encapsulate, and
decapsulate with MlKem.decapsulate.
Details#
Each function takes the parameter set and the caller's buffers, which must have the lengths of
MlKemParameters. The decapsulation key holds the encapsulation key; see
MlKem.encapsulationKeyOf.
Implementation MlKem#
impl MlKemAssociated function keyPairFromSeed#
pub fn keyPairFromSeed(
parameters: MlKemParameters,
seed: &[u8],
encapsulationKey: &mut [u8],
decapsulationKey: &mut [u8],
) -> Result<(), MlKemError>Writes the key pair of ML-KEM.KeyGen_internal for the 64-byte seed, d followed by z,
into encapsulationKey and decapsulationKey.
Errors#
InvalidLengthifseedis not 64 bytes, or a key buffer does not have the length of the parameter set. The buffers do not change.
Associated function generateSeed#
pub effect fn generateSeed() -> [u8; 64] ? &mut RandomReturns a new 64-byte seed from the ambient Random, for MlKem.keyPairFromSeed.
The Random provider must be cryptographically secure.
Associated function encapsulationKeyOf#
pub fn encapsulationKeyOf<'a>(parameters: MlKemParameters, decapsulationKey: &'a [u8]) -> Result<
&'a [u8],
MlKemError,
>Returns the encapsulation key inside decapsulationKey, a view that does not copy.
Errors#
InvalidLengthifdecapsulationKeydoes not have the length of the parameter set.
Associated function checkEncapsulationKey#
pub fn checkEncapsulationKey(parameters: MlKemParameters, encapsulationKey: &[u8]) -> Result<
(),
MlKemError,
>Checks an encapsulation key as FIPS 203 section 7.2 asks: the length, and that every coefficient is below q.
Errors#
InvalidLengthorInvalidEncapsulationKey.
Associated function checkDecapsulationKey#
pub fn checkDecapsulationKey(parameters: MlKemParameters, decapsulationKey: &[u8]) -> Result<
(),
MlKemError,
>Checks a decapsulation key as FIPS 203 section 7.3 asks: the length, and that it holds the SHA3-256 hash of its encapsulation key.
Errors#
InvalidLengthorInvalidDecapsulationKey.
Associated function encapsulate#
pub effect fn encapsulate(
parameters: MlKemParameters,
encapsulationKey: &[u8],
ciphertext: &mut [u8],
) -> Result<[u8; 32], MlKemError> ? &mut RandomWrites a ciphertext for encapsulationKey into ciphertext and returns the 32-byte shared
secret, with a 32-byte message from the ambient Random.
Errors#
InvalidLengthifencapsulationKeyorciphertextdoes not have the length of the parameter set.InvalidEncapsulationKeyif the key fails the modulus check.
ciphertext does not change on an error.
Associated function encapsulateWith#
pub fn encapsulateWith(
parameters: MlKemParameters,
encapsulationKey: &[u8],
message: &[u8],
ciphertext: &mut [u8],
) -> Result<[u8; 32], MlKemError>Writes the ciphertext of ML-KEM.Encaps_internal for encapsulationKey and the 32-byte
message into ciphertext, and returns the shared secret.
Errors#
InvalidLengthfor a key, message, or ciphertext buffer of the wrong length.InvalidEncapsulationKeyif the key fails the modulus check.
Gotchas#
It is for test vectors. A message that is not fresh random bytes breaks the security, so use
MlKem.encapsulate.
Associated function decapsulate#
pub fn decapsulate(parameters: MlKemParameters, decapsulationKey: &[u8], ciphertext: &[u8]) -> Result<
[u8; 32],
MlKemError,
>Returns the 32-byte shared secret of ML-KEM.Decaps for ciphertext.
A ciphertext of the right length that was not made for this key gives the implicit-rejection secret of FIPS 203, a value that the sender cannot predict, and not an error. The time does not depend on the secret values or on whether the ciphertext matched.
Errors#
InvalidLengthifdecapsulationKeyorciphertextdoes not have the length of the parameter set.InvalidDecapsulationKeyif the key fails the hash check.
Category: Cryptography.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2, x86_64-pc-windows-msvc, wasm64-unknown-unknown.