ConstantTimeCompare compares two byte slices while avoiding timing differences based on their contents. It returns 1 for equal contents and 0 otherwise. Unequal lengths return 0 immediately, so its runtime depends on length; equal-length inputs are processed without stopping at the first mismatch. section 10.4.1
The implementation avoids the early-exit failure found in ordinary comparisons:
- XOR each pair of bytes and accumulate every difference in v. section 10.4.1
- Convert the final accumulator to equality through ConstantTimeByteEq rather than a standard comparison. section 10.4.1
- Avoid ordinary memcmp-style loops, which stop at the first mismatched byte and reveal how much input matched. section 10.4.1
Listing 10.2 Constant-time comparisons in the crypto/subtle Go package
func ConstantTimeCompare(x, y []byte) int {
if len(x) != len(y) {
return 0
}
var v byte
for i := 0; i < len(x); i++ {
v |= x[i] ^ y[i]
}
return ConstantTimeByteEq(v, 0)
}
// ...
func ConstantTimeByteEq(x, y uint8) int {
return int((uint32(x^y) - 1) >> 31)
}
Inspect the Go implementation showing length handling, XOR accumulation, and the ConstantTimeByteEq helper. section 10.4.1
