Skip to content
hashkey.bond

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.