// src/lib/crypto.ts
import { scrypt } from "@noble/hashes/scrypt.js";
import { randomBytes } from "@noble/hashes/utils.js";
var encoder = new TextEncoder();
var randomHex = (bytes) => {
  const arr = randomBytes(bytes);
  return Array.from(arr, (b) => b.toString(16).padStart(2, "0")).join(
    ""
  );
};
var toHex = (buffer) => {
  return Array.from(
    buffer,
    (b) => b.toString(16).padStart(2, "0")
  ).join("");
};
var hexToBytes = (hex) => {
  const bytes = new Uint8Array(hex.length / 2);
  for (let i = 0; i < hex.length; i += 2) {
    bytes[i / 2] = Number.parseInt(hex.slice(i, i + 2), 16);
  }
  return bytes;
};
var SCRYPT_KEYLEN = 64;
var SCRYPT_COST = 16384;
var SCRYPT_BLOCK_SIZE = 8;
var SCRYPT_PARALLELISM = 1;
var hashPassword = async (password) => {
  const salt = randomBytes(16);
  const saltHex = toHex(salt);
  const passwordBytes = encoder.encode(password);
  const derivedKey = await Promise.resolve(
    scrypt(passwordBytes, salt, {
      N: SCRYPT_COST,
      r: SCRYPT_BLOCK_SIZE,
      p: SCRYPT_PARALLELISM,
      dkLen: SCRYPT_KEYLEN
    })
  );
  return `${saltHex}:${toHex(derivedKey)}`;
};
var verifyPassword = async (password, hashed) => {
  if (!hashed) {
    return false;
  }
  const [saltHex, keyHex] = hashed.split(":");
  if (!(saltHex && keyHex)) {
    return false;
  }
  const salt = hexToBytes(saltHex);
  const passwordBytes = encoder.encode(password);
  const derivedKey = await Promise.resolve(
    scrypt(passwordBytes, salt, {
      N: SCRYPT_COST,
      r: SCRYPT_BLOCK_SIZE,
      p: SCRYPT_PARALLELISM,
      dkLen: SCRYPT_KEYLEN
    })
  );
  const derived = toHex(derivedKey);
  if (derived.length !== keyHex.length) {
    return false;
  }
  let result = 0;
  for (let i = 0; i < derived.length; i++) {
    result |= derived.charCodeAt(i) ^ keyHex.charCodeAt(i);
  }
  return result === 0;
};
var hashToken = async (token, secret) => {
  if (!secret || secret.length === 0) {
    throw new Error(
      "AUTH_SECRET is required and must be a non-empty string. Please set AUTH_SECRET environment variable."
    );
  }
  const key = await crypto.subtle.importKey(
    "raw",
    encoder.encode(secret),
    { name: "HMAC", hash: "SHA-256" },
    false,
    ["sign"]
  );
  const signature = await crypto.subtle.sign(
    "HMAC",
    key,
    encoder.encode(token)
  );
  return toHex(new Uint8Array(signature));
};
var generateToken = (bytes = 48) => randomHex(bytes);
var hashVerificationCode = (code, secret) => hashToken(code, secret);
export {
  generateToken,
  hashPassword,
  hashToken,
  hashVerificationCode,
  verifyPassword
};
//# sourceMappingURL=crypto.js.map