Use constant-time comparison for secret verification
When comparing secrets (passwords, tokens, MACs), the comparison must take time independent of the values to prevent timing side-channels.
- 1
A constant-time comparison processes all bytes regardless of where mismatches occur. It accumulates differences with XOR and OR, then checks the accumulator at the end. This prevents an attacker from learning how many bytes match based on execution time.
- 2 Hash Compare →
Compare two hash values using constant-time comparison. The tool always processes all bytes of both inputs, regardless of match position. Use this for verifying HMACs, password hashes, and API tokens.
- 3 HMAC Generator →
After generating an HMAC, verify it with constant-time comparison. The pattern is: compute expected = HMAC(key, message), then constantTimeEqual(expected, received). Never use === or != for this comparison.
- 4
In Node.js, use crypto.timingSafeEqual(a, b). In browsers, implement it manually: accumulate XOR of all bytes, check the result. Both inputs must be the same length — if lengths differ, return false immediately (length is not secret). The comparison itself must be constant-time only when lengths match.
Frequently asked questions
- What if the lengths are different?
- Return false immediately. The length of a hash or token is typically not secret (it is fixed by the algorithm). The constant-time requirement applies only to the byte-by-byte comparison of equal-length inputs. Comparing different-length values in constant time is unnecessary.
- Does this matter over a network?
- Yes. Timing attacks have been demonstrated over networks with ~15ms jitter. While harder than local attacks, they are feasible with enough samples. For high-value targets (API keys, payment tokens), always use constant-time comparison, even over network.
Workflows that solve this
Learn more
Want to understand why?