11# ML-KEM OT Protocol
22
3- Based on MR19 (Masny-Rindal, ePrint 2019/706), Figure 8, instantiated with ML-KEM per Section D.3.
3+ Based on MR19 (Masny-Rindal, ePrint 2019/706), Figure 8, instantiated with ML-KEM instead of Crystals-Kyber, as per Section D.3.
44
5- Reference implementation: [ libOTe KyberOT] ( []( https://github.com/osu-crypto/libOTe/blob/d0e499206d1d4d16c6b4ca6c0e712490e0632f80/thirdparty/KyberOT/KyberOT.c#L40-L41) ) .
5+ Reference implementation: [ libOTe KyberOT] ( https://github.com/osu-crypto/libOTe/blob/d0e499206d1d4d16c6b4ca6c0e712490e0632f80/thirdparty/KyberOT/KyberOT.c#L40-L41 ) .
66
7- ML-KEM implementation: [ ML-KEM] ( []( https://github.com/RustCrypto/KEMs/blob/5a7f3ab7af5420cacca9befc9212532e4c7f6ca1/ml-kem/src/) ) .
7+ ML-KEM implementation: [ ML-KEM] ( https://github.com/RustCrypto/KEMs/blob/5a7f3ab7af5420cacca9befc9212532e4c7f6ca1/ml-kem/src/ ) .
88
99## Notation
1010
3030- ` t_hat ` is an ` NttVector<k> ` : the public key vector in NTT domain (` t_hat = A_hat * s + e ` in NTT form)
3131- ` rho ` is a 32-byte seed used to derive the public matrix ` A_hat `
3232
33- Note that the ML-KEM encapsulation key is the same as the K-PKE encryption key in our simplified outline above .
33+ Note that the ML-KEM encapsulation key is the same as the K-PKE encryption key (FIPS 203, Section 5) .
3434
3535The serialized form is:
3636
@@ -65,16 +65,14 @@ for j in 0..k:
6565```
6666
6767Each call uses different index bytes ` (j, 0) ` in FIPS 203 Algorithm 7 for domain separation.
68- In libOTe, this corresponds to ` randomPK ` , where it instead generates ` A_hat ` and takes a single
69- row or column from it.
68+ In libOTe, this corresponds to ` randomPK ` , where it instead generates ` A_hat ` and takes the first row from it.
7069
7170Output: ` (t_hat, rho) ` . The ` rho ` is passed through unchanged.
7271
7372** ` H(ek) -> (h, ek.rho) ` **
7473
7574Hash-to-key (corresponds to libOTe's ` pkHash ` ). Maps an encapsulation key to another
76- encapsulation key. Takes an element of ` T_q^k ` , hashes it
77- to a 32-byte seed, and uses that seed to sample a new element of ` T_q^k ` .
75+ encapsulation key. Takes an element of ` T_q^k ` , hashes it to a 32-byte seed, and uses that seed to sample a new element of ` T_q^k ` .
7876
7977Given an encapsulation key ` ek = (t_hat, rho) ` :
8078
@@ -85,7 +83,7 @@ h = SampleNTTVector(seed, ek.rho) // sample a new NttVector<k> from t
8583
8684Output: ` (h, ek.rho) ` where ` h ` is an ` NttVector<k> ` in ` T_q^k ` .
8785
88- ** ` RandomEK(seed, rho) -> (r_hat , rho) ` **
86+ ** ` RandomEK(seed, rho) -> (t_hat , rho) ` **
8987
9088Generate a random encapsulation key from the given random 32 byte ` seed ` and ` rho ` :
9189
@@ -140,7 +138,7 @@ component only. The `rho` component is always the same across all keys in a sing
140138 ```
141139 Each ` ss_j ` is a 32-byte ML-KEM shared secret. Each ` ct_j ` is an ML-KEM ciphertext.
142140
143- 8 . ** Derive OT output keys**
141+ 8 . ** Derive OT output keys**
144142
145143 Hashing each shared secret down to a 128-bit ` Block ` :
146144 ```
@@ -168,7 +166,7 @@ component only. The `rho` component is always the same across all keys in a sing
168166 ```
169167 key_b = RO(domain_sep || ss_b || i)
170168 ```
171- The receiver stores `ots[i] = key_b` — one OT output key for OT `i` batch in the batch.
169+ The receiver stores `ots[i] = key_b` — one OT output key for the `i`-th OT in the batch.
172170
173171## Why This Works
174172
@@ -199,7 +197,7 @@ cancel with `H(r_{1-b})`. The result `ek_{1-b}` is an unrelated key for which th
199197receiver does not have a decapsulation key `dk`, so they cannot decapsulate `ct_{1-b}`.
200198
201199The choice bit `b` is hidden because `r_b = ek - H(r_{1-b})`. Since `ek` is
202- indistinguishable from uniform under MLWE, and `H(r_{1-b})` is determined by the
200+ indistinguishable from uniform under the MLWE assumption , and `H(r_{1-b})` is determined by the
203201already-public `r_{1-b}`, subtracting it from a uniform value still yields a uniform
204202value. So both `r_0` and `r_1` appear uniform to the sender — neither reveals which
205203is the real key.
0 commit comments