# constantTimeEqual _(no submodules)_ ## Purpose Byte-for-byte comparison of two `Uint8Array` buffers that takes time dependent only on the input length, not on where they first differ. Use it — and never the built-in `===`, `Array.prototype.every`, or `Buffer.equals` — for comparing authentication tags, MAC digests, password hashes, and any other value where an attacker might use wall-clock time to learn a secret byte-by-byte. ## Features - No early return on mismatch within the byte loop. - Constant-time in buffer **contents**; length check is the only short-circuit (lengths of MACs/tags are public constants). - Zero allocations; pure loop over the inputs. - No dependencies. ## Usage: Basic Example ```ts import { constantTimeEqual } from "@suaveplan/crypto-utils/constant-time"; const tagReceived = new Uint8Array(16); const tagExpected = new Uint8Array(16); if (!constantTimeEqual(tagReceived, tagExpected)) { throw new Error("tag mismatch"); } ``` ## Usage: Advanced Example ```ts import { constantTimeEqual } from "@suaveplan/crypto-utils/constant-time"; // Verify a computed MAC against a header-supplied expected MAC in one step, // without ever comparing via `===`, `for-of`, or `Buffer.equals`. function verifyMessageAuth( macImpl: (msg: Uint8Array) => Uint8Array, message: Uint8Array, expected: Uint8Array ): boolean { const computed = macImpl(message); return constantTimeEqual(computed, expected); } ``` ## API Reference - `constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean` — returns `true` iff both buffers have the same length **and** every byte matches. When lengths differ, returns `false` immediately (length is not secret). ## Implementation Notes The loop computes `diff |= a[i] ^ b[i]`, accumulating a nonzero value iff any pair of bytes differs; the final check `diff === 0` is also constant time because it inspects a single integer. JavaScript engines aggressively inline this pattern, so the generated machine code is effectively identical to the hand-written one found in `@noble/hashes` and `libsodium`'s `sodium_memcmp`. The length short-circuit exists because returning `false` on length mismatch does not leak secret information — MAC and tag lengths are public protocol constants — and because continuing the loop with a shorter buffer would require masking that adds complexity with no security benefit.