Archivecryptography
Writing Constant-Time Code Without Lying to Yourself
Branching on secret bytes leaks through timing. Here is what actually helps and what only looks like it does.
- Published
- Reading time
- 1 min read
If execution time depends on a secret, an attacker with enough samples can recover it. Comparisons, table lookups, and early exits are the usual culprits.
What leaks
// leaks the first differing byte
for (i = 0; i < n; i++) if (a[i] != b[i]) return 0;
Fix with an accumulator that touches every byte:
diff = 0;
for (i = 0; i < n; i++) diff |= a[i] ^ b[i];
return diff == 0;
Careful: the compiler may still vectorize or transform this. Use the language's audited primitive (crypto.subtle.timingSafeEqual, hmac.compare_digest, subtle.ConstantTimeCompare) instead of hand-rolling.
What does not help
- Adding random sleeps — noise averages out.
- Comparing hashes of secrets with
==— the hash comparison still short-circuits. - Length hiding without fixing content comparisons.
Takeaway: use vetted constant-time primitives, compare MACs not plaintexts, and treat "it looks branchless" as unproven until measured.