crypto.constant-time-equal@1.0.0
impl/typescript.ts
1,015 bytes · the TypeScript implementation · view raw
function checkBytes(value: readonly number[], name: string): void {
if (!Array.isArray(value) && !(value instanceof Uint8Array)) {
throw new TypeError(`${name} must be a list of integers from 0 to 255`);
}
for (let i = 0; i < value.length; i++) {
const b = value[i];
if (typeof b !== "number" || !Number.isInteger(b) || b < 0 || b > 255) {
throw new RangeError(`${name} must be a list of integers from 0 to 255`);
}
}
}
/**
* Are two byte strings equal, without stopping at the first difference?
* Every byte is visited and the differences OR-ed together, so the time
* taken says nothing about where a forged tag goes wrong. Different lengths
* answer false at once: a digest's length is not a secret.
*/
export function constantTimeEqual(a: readonly number[], b: readonly number[]): boolean {
checkBytes(a, "a");
checkBytes(b, "b");
if (a.length !== b.length) return false;
let diff = 0;
for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
return diff === 0;
}