import crypto from 'node:crypto'; /** * Constant-time string comparison for secrets (e.g. the owner bearer token). * * Plain `===` short-circuits on the first differing byte, leaking length and * prefix via timing. `crypto.timingSafeEqual` is constant-time but THROWS when * the two buffers differ in length — so we length-check first (length is not * the secret) and only then do the constant-time compare. Returns false for * any falsy / non-string input rather than throwing. * * @param {string} a * @param {string} b * @returns {boolean} */ export function timingSafeStrEqual(a, b) { if (typeof a !== 'string' || typeof b !== 'string') return false; if (a.length === 0 || b.length === 0) return false; const ab = Buffer.from(a); const bb = Buffer.from(b); if (ab.length !== bb.length) return false; return crypto.timingSafeEqual(ab, bb); }