/**
 * Constant-time string comparison.
 *
 * Use this for every admin-secret / bearer-token / HMAC comparison. Naive
 * `a === b` short-circuits on the first byte mismatch, leaking length
 * information that an attacker can use to slow-search the secret.
 *
 * `crypto.timingSafeEqual` requires equal-length buffers and runs in
 * constant time. We normalise to UTF-8 buffers, pad shorter to longer
 * with zero bytes so length mismatch is also constant-time, and OR a
 * length-mismatch flag at the end so different lengths can't return true.
 */
import { timingSafeEqual } from "crypto";

export function timingSafeStringEq(a: string, b: string): boolean {
  const aBuf = Buffer.from(a, "utf8");
  const bBuf = Buffer.from(b, "utf8");
  const max = Math.max(aBuf.length, bBuf.length);
  const aPadded = Buffer.alloc(max);
  const bPadded = Buffer.alloc(max);
  aBuf.copy(aPadded);
  bBuf.copy(bPadded);
  const equal = timingSafeEqual(aPadded, bPadded);
  // Length mismatch defeats the compare even if padded prefixes happen to match.
  return equal && aBuf.length === bBuf.length;
}
