Skip to content
All articles
Audit report

From the audit floor: variable-time decapsulation and the KyberSlash class

By qproof Audit5 min
TL;DR

The finding

ML-KEM requires constant-time decapsulation because the reject-vs-accept distinction must not be observable. We have found implementations whose decapsulation branched in a timing-distinguishable way — the KyberSlash class targets exactly this. Verify constant-time at the binary level.

ML-KEM tolerates implicit rejection by design: on an invalid ciphertext it returns a deterministic pseudo-random shared secret rather than an error. That property is only safe if the path that produces it is indistinguishable, by timing, from the accepting path.

Constant-time, undone by the compiler

A subtler version of the same class: source code that is written to be constant-time but is compiled into branchy code by the optimiser. The property the developer reasoned about at the source level no longer holds in the binary the machine actually runs.

From the audit floor

Verify at the binary level

Check the constant-time property where it matters — at the binary level, with tools like ctgrind, TIMECOP, or dudect — not at the source level. The KyberSlash class of timing attacks specifically exploits the gap between source-level intent and compiled reality.

Pitfall

Weak randomness in keygen

A related and surprisingly common bug: keygen drawing randomness from a non-cryptographic source, or one that has not been seeded. Post-quantum primitives have specific entropy requirements — a working implementation does not prove the RNG path is sound.

Have a system that needs this?

Secure my organization