Constant-Time String Comparison
Compare secrets without early exit by XOR-ing UTF-8 bytes, reducing timing leaks in token and signature checks.
Code
const encoder = new TextEncoder();
// Constant-time comparison for secrets and signatures.
export function constantTimeEqual(left, right) {
const a = encoder.encode(String(left));
const b = encoder.encode(String(right));
const length = Math.max(a.length, b.length);
let difference = a.length ^ b.length;
for (let index = 0; index < length; index += 1) {
difference |= (a[index] ?? 0) ^ (b[index] ?? 0);
}
return difference === 0;
}
export function constantTimeEqualBytes(left, right) {
if (!(left instanceof Uint8Array) || !(right instanceof Uint8Array)) {
throw new TypeError("both arguments must be Uint8Array values");
}
const length = Math.max(left.length, right.length);
let difference = left.length ^ right.length;
for (let index = 0; index < length; index += 1) {
difference |= (left[index] ?? 0) ^ (right[index] ?? 0);
}
return difference === 0;
}Report a problem with this exampleOpens a pre-filled issue on GitHub.