import { randomBytes, scrypt as scryptCallback, timingSafeEqual } from "node:crypto"; import { promisify } from "node:util"; const scrypt = promisify(scryptCallback) as (password: string, salt: Buffer, keylen: number) => Promise; /** Returns "scrypt$$" (base64). */ export async function hashPassword(password: string): Promise { const salt = randomBytes(16); const hash = await scrypt(password, salt, 64); return `scrypt$${salt.toString("base64")}$${hash.toString("base64")}`; } export async function verifyPassword(password: string, stored: string): Promise { const [algorithm, salt, hash] = stored.split("$"); if (algorithm !== "scrypt" || !salt || !hash) return false; const expected = Buffer.from(hash, "base64"); const actual = await scrypt(password, Buffer.from(salt, "base64"), expected.length); return timingSafeEqual(actual, expected); }