Kyeson

Essay · 2 min read

Constant-time is a property of the binary, not the source

You can write perfectly branch-free crypto code and still ship a timing leak. The compiler gets the last word.

Cryptographic code that handles secrets has to run in constant time. If comparing a secret key or MAC takes slightly longer when more bytes match, an attacker who can measure that timing can recover the secret one byte at a time. This isn't theoretical: timing attacks have recovered keys over networks.

The standard advice is to avoid branches and early exits that depend on secret data. Compare every byte, combine the results with bitwise operations, and only look at the answer at the end. That advice is correct. It just isn't enough.

The compiler doesn't share your goal

A compiler's job is to make code fast while preserving its observable result. Timing isn't part of that contract. An optimizer that notices your careful branch-free comparison can be short-circuited is allowed to put the branch back. Sometimes it does.

The same thing happens in subtler ways. A lookup table indexed by a secret value leaks through cache timing. Some CPUs take a variable number of cycles for division or certain multiplications. A conditional move you expected can turn into a conditional jump on a different architecture or optimization level.

Until you've verified the binary, constant time is something you intended, not something you have.

How to actually get constant-time code

Don't write it yourself if you can avoid it. Use well-maintained libraries whose authors test for timing behavior, and use their comparison functions instead of your language's equality operator.

Read the output. If you do maintain secret-handling code, inspect the generated assembly for the build configurations you ship. A tool like Compiler Explorer makes this practical for a single function.

Test empirically. Statistical timing-analysis tools run a function with different classes of input and flag measurable differences. They catch problems that code review won't.

Re-check after changes. A compiler upgrade, a new target architecture or a change in optimization flags can undo constant-time behavior without touching a line of source.

This matters more as teams adopt post-quantum algorithms, which bring new implementations and fresh opportunities for side channels. Until you've verified the binary, a constant-time property is something you intended, not something you have.

Constant-time is a property of the binary, not the source: an essay by Kyeson Blake Utley
Share card for this essay by Kyeson Blake Utley.
Kyeson Blake Utley is the founder of GhostKey Development. More essays are on the home page, and his projects are at kyesonblakeutley.com.