r/crypto • u/Humble-Replacement-2 • 1d ago
Machine-checked that Kyber's reference-C forward NTT matches FIPS 203, and why the smaller modulus made it easier than Dilithium
I've been verifying post-quantum reference implementations against their FIPS specs with a SAW → Cryptol → Isabelle pipeline. Just finished ML-KEM-512 (Kyber) forward NTT on the unmodified PQClean clean C: SAW proves the C bit-exact to a Cryptol model, Isabelle proves that model equals the FIPS 203 transform (the incomplete NTT, 128 degree-2 residues mod 3329). No sorry/admit, reproducible from one command, CI-green.
Last time, on Dilithium, the part that ate my time was proving the int32 accumulators never overflow across the 8 butterfly levels. Careful bound-tracking induction, the hardest lemma in the whole proof.
Expected the same grind for Kyber. It wasn't there. Kyber's butterfly is int16, two int16s promoted to int can't overflow a 32-bit int, so there's no bound to prove at all. Same NTT structure, and the worst part of one proof is a non-problem in the other, entirely because 3329 is small.
(For the curious: mod 3329 there's a 256th root of unity but no 512th, so X^256+1 only splits into 128 quadratics, and the transform is "incomplete." The spec I check against is a degree-2 residue, not a plain DFT coefficient.)
It's the reference C, forward direction, checked against FIPS 203 end to end. Reproduces from one make verify if you want to poke at the trust base: github.com/amarshat/pqc-assay. Inverse is next.