Notebook 09 — What we built#

Across nine notebooks we built toy LWE, broke it at small parameters, learned why the polynomial ring Z_q[x]/(x^n+1) plus NTT makes ML-KEM fast, and implemented FIPS 203 ML-KEM (512/768/1024) with passing roundtrip and size tests.

The one-paragraph test#

Try writing, without looking back, a five-sentence explanation of ML-KEM that covers:

  • What problem is hard (LWE / Module-LWE)

  • Why the ring structure helps (NTT, compact keys)

  • What K-PKE does (encrypt to a public (A, t = A s + e))

  • Why the FO transform is there (upgrade from CPA to CCA security)

  • What a shared secret is derived from (a hash of the encapsulated message)

If you can’t cover one of those, that’s the notebook to re-read.

Gaps vs. production#

  • Constant-time arithmetic: real implementations avoid secret-dependent branches and memory access. Ours uses Python ints and numpy which are not constant-time.

  • Side-channel resistance: countermeasures against cache timing, power, EM side channels. Out of scope here.

  • NIST Known-Answer Tests (KATs): we did not verify bit-for-bit equivalence with FIPS 203 test vectors (different byte-packing subtleties could make us incompatible on the wire). Our tests show self-consistency, not interoperability.

  • Safe memory clearing: Python has no portable way to zero memory reliably after use.

  • Audited dependencies: we rely on hashlib (OK) and numpy (for speed only).

Further reading#

  • FIPS 203 — ML-KEM Standard (NIST, 2024). The authoritative spec.

  • Regev 2005On Lattices, Learning With Errors, Random Linear Codes, and Cryptography (STOC’05). The original LWE paper.

  • Peikert 2016A Decade of Lattice Cryptography. Comprehensive survey.

  • LWE Estimator (Albrecht, Player, Scott) — github.com/malb/lattice-estimator. The community-standard tool for assessing concrete LWE hardness.

  • kyber-py (Giacon) — a clean reference Python implementation of Kyber/ML-KEM if you want to compare.

Where to go next#

  • ML-DSA (Dilithium, FIPS 204) — lattice-based signatures using the same Module-LWE/SIS foundation.

  • SLH-DSA (SPHINCS+, FIPS 205) — stateless hash-based signatures. Different math: uses only hash functions; much larger signatures but minimal assumptions.

  • BIKE / HQC / Classic McEliece — code-based KEMs. NIST’s alternate track.

  • Hybrid in practice — read draft-ietf-tls-hybrid-design and watch the upcoming TLS 1.3 hybrid rollout (Chrome has deployed X25519+Kyber since 2023).

Hands-on capstone: pq-messenger — a Signal-style end-to-end encrypted CLI that uses the pqc_edu ML-KEM you just built, in a hybrid X25519 + ML-KEM-768 X3DH handshake plus a full Double Ratchet (symmetric chain + DH rotation, since v0.2). Two real OS processes, a shared file queue, every byte visible.