← back to Govarbitrage

src/lib/password.ts

22 lines

import crypto from "node:crypto";

// Password hashing with Node's built-in scrypt — no native deps. Format:
// "scrypt$<saltHex>$<derivedKeyHex>". Node-runtime only (login route).

const KEYLEN = 64;

export function hashPassword(password: string): string {
  const salt = crypto.randomBytes(16).toString("hex");
  const dk = crypto.scryptSync(password, salt, KEYLEN).toString("hex");
  return `scrypt$${salt}$${dk}`;
}

export function verifyPassword(password: string, stored: string): boolean {
  const parts = stored.split("$");
  if (parts.length !== 3 || parts[0] !== "scrypt") return false;
  const [, salt, dkHex] = parts;
  const expected = Buffer.from(dkHex, "hex");
  const actual = crypto.scryptSync(password, salt, KEYLEN);
  return expected.length === actual.length && crypto.timingSafeEqual(expected, actual);
}