import { hash, verify } from "@node-rs/argon2";

// Argon2id with OWASP-recommended minimums (19 MiB, 2 iterations, 1 lane).
const ARGON2_OPTIONS = {
  memoryCost: 19456,
  timeCost: 2,
  parallelism: 1,
  outputLen: 32,
};

export const PASSWORD_MIN_LENGTH = 8;
export const PASSWORD_MAX_LENGTH = 200;

export function hashPassword(password: string): Promise<string> {
  return hash(password, ARGON2_OPTIONS);
}

export async function verifyPassword(passwordHash: string, password: string): Promise<boolean> {
  try {
    return await verify(passwordHash, password);
  } catch {
    return false;
  }
}

// Verified against when the username doesn't exist, so a missing user costs
// the same time as a wrong password and usernames can't be probed by timing.
let dummyHash: Promise<string> | undefined;

export function verifyAgainstDummy(password: string): Promise<boolean> {
  dummyHash ??= hashPassword("dummy-password-for-timing-only");
  return dummyHash.then((h) => verifyPassword(h, password)).then(() => false);
}
