Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR adds
crypto.utilstobasis/crypto, providing common utility functions for cryptographic implementations.Overview
Cryptographic code often requires operations that are resistant to side-channel attacks. This vocabulary provides such utilities, starting with three constant-time operations.
Implementation Details
constant-time=compares two byte sequences in constant time:constant-time-zero?checks if all bytes are zero:constant-time-selectselects between two integers without branching:flag negconverts flag to a bitmask: flag = 1 -> -1 (all bits set), flag = 0 -> 0a mask bitandkeeps a if mask is all 1s, zeroes it if mask is 0b mask bitnot bitanddoes the opposite for bbitorcombines them: one term keeps its value, the other is zeroedNote on flag type: The flag parameter is 0/1 rather than boolean because Factor's
?word introduces a branch, which would defeat the purpose of constant-time selection. Usingflag negis fully branchless.If you have a boolean and the condition itself is not secret, you can convert with
1 0 ?:Why is this needed?
Standard comparison functions like
=andsequence=return early on the first mismatch:An attacker can exploit this timing difference to break MAC verification byte-by-byte. For each byte position, they try all 256 possible values and measure which one takes longest (indicating a match). This reduces a 2^128 brute force to ~256 * 16 = 4096 attempts for a 16-byte tag.
Similarly, conditional branches can leak information through timing or speculative execution. The
constant-time-selectfunction avoids this by using arithmetic operations that always execute the same instructions regardless of the flag value.The same principle applies to
constant-time-zero?. A naive implementation like0 [ = ] all?returns early on the first non-zero byte, revealing its position. The constant-time version always examines all bytes.Usage
Testing
constant-time=(14 tests):constant-time-zero?(9 tests):constant-time-select(10 tests):Future Work
This vocabulary is a prerequisite for
crypto.poly1305and other cryptographic implementations that require constant-time operations.