Implementation of the IND-CCA2 post-quantum secure key encapsulation mechanism (KEM) CRYSTALS-Kyber, as submitted to the third round of the NIST Post-Quantum Cryptography (v3.02/“draft00”), and selected for standardisation.
Kyber will likely change before final standardisation.
The namespace suffix (currently _d00
) refers to the version currently implemented, in accordance with the draft. It may not be updated if new versions of the draft only include editorial changes.
The suffix will eventually be removed once Kyber is finalized.
Quoting from the CFRG I-D:
Kyber is not a Diffie-Hellman (DH) style non-interactive key agreement, but instead, Kyber is a Key Encapsulation Method (KEM). In essence, a KEM is a Public-Key Encryption (PKE) scheme where the plaintext cannot be specified, but is generated as a random key as part of the encryption. A KEM can be transformed into an unrestricted PKE using HPKE (RFC9180). On its own, a KEM can be used as a key agreement method in TLS.
Kyber is an IND-CCA2 secure KEM. It is constructed by applying a Fujisaki–Okamato style transformation on InnerPKE, which is the underlying IND-CPA secure Public Key Encryption scheme. We cannot use InnerPKE directly, as its ciphertexts are malleable.
F.O. transform
InnerPKE ----------------------> Kyber
IND-CPA IND-CCA2
Kyber is a lattice-based scheme. More precisely, its security is based on the learning-with-errors-and-rounding problem in module lattices (MLWER). The underlying polynomial ring R (defined in Section 5) is chosen such that multiplication is very fast using the number theoretic transform (NTT, see Section 5.1.3).
An InnerPKE private key is a vector s over R of length k which is small in a particular way. Here k is a security parameter akin to the size of a prime modulus. For Kyber512, which targets AES-128’s security level, the value of k is 2.
The public key consists of two values:
-
A a uniformly sampled k by k matrix over R and
-
t = A s + e, where e is a suitably small masking vector.
Distinguishing between such A s + e and a uniformly sampled t is the module learning-with-errors (MLWE) problem. If that is hard, then it is also hard to recover the private key from the public key as that would allow you to distinguish between those two.
To save space in the public key, A is recomputed deterministically from a seed rho.
A ciphertext for a message m under this public key is a pair (c_1, c_2) computed roughly as follows:
c_1 = Compress(A^T r + e_1, d_u) c_2 = Compress(t^T r + e_2 + Decompress(m, 1), d_v)
where
-
e_1, e_2 and r are small blinds;
-
Compress(-, d) removes some information, leaving d bits per coefficient and Decompress is such that Compress after Decompress does nothing and
-
d_u, d_v are scheme parameters.
Distinguishing such a ciphertext and uniformly sampled (c_1, c_2) is an example of the full MLWER problem, see section 4.4 of [KyberV302].
To decrypt the ciphertext, one computes
m = Compress(Decompress(c_2, d_v) - s^T Decompress(c_1, d_u), 1).
It it not straight-forward to see that this formula is correct. In fact, there is negligible but non-zero probability that a ciphertext does not decrypt correctly given by the DFP column in Table 4. This failure probability can be computed by a careful automated analysis of the probabilities involved, see kyber_failure.py of [SecEst].