// src/secure-store/kdf.ts
import { scryptSync, timingSafeEqual } from "crypto";
import { createRequire } from "module";
var requireArgon2 = createRequire(import.meta.url);
var argon2Runtime;
function loadArgon2Runtime() {
  try {
    argon2Runtime ??= requireArgon2("@node-rs/argon2");
    return argon2Runtime;
  } catch (cause) {
    throw new Error(
      "Argon2id KDF requires @node-rs/argon2 to be installed and loadable on this platform. Use scrypt compatibility mode for stores that must run without the Argon2 native binding.",
      { cause }
    );
  }
}
var DEFAULT_SCRYPT_PARAMS = Object.freeze({
  // 2^17. Hex-coding the literal would obscure the doubling chain.
  N: 1 << 17,
  r: 8,
  p: 1,
  keyLength: 32,
  // 256 MiB ceiling — comfortably above the 128 MiB scrypt needs at N=2^17.
  maxmem: 256 * 1024 * 1024
});
var DEFAULT_ARGON2ID_PARAMS = Object.freeze({
  memoryKiB: 64 * 1024,
  iterations: 3,
  parallelism: 4,
  keyLength: 32
});
var KDF_SALT_LENGTH = 16;
var KDF_KEY_LENGTH = 32;
function validateScryptParams(params) {
  const { N, r, p, keyLength, maxmem } = params;
  if (!Number.isInteger(N) || N < 2) {
    throw new Error(`scrypt N must be an integer \u2265 2, got ${N}`);
  }
  if (N > 2 ** 30) {
    throw new Error(`scrypt N is unreasonably large (max 2^30), got ${N}`);
  }
  if (!Number.isInteger(Math.log2(N))) {
    throw new Error(`scrypt N must be a power of 2, got ${N}`);
  }
  if (!Number.isInteger(r) || r < 1) {
    throw new Error(`scrypt r must be a positive integer, got ${r}`);
  }
  if (!Number.isInteger(p) || p < 1) {
    throw new Error(`scrypt p must be a positive integer, got ${p}`);
  }
  if (!Number.isInteger(keyLength) || keyLength < 16) {
    throw new Error(
      `scrypt keyLength must be \u2265 16 (need 32 for AES-256), got ${keyLength}`
    );
  }
  if (!Number.isInteger(maxmem) || maxmem < 1024) {
    throw new Error(`scrypt maxmem must be a sane positive integer, got ${maxmem}`);
  }
}
function validateArgon2idParams(params) {
  const { memoryKiB, iterations, parallelism, keyLength } = params;
  if (!Number.isInteger(memoryKiB) || memoryKiB < 8) {
    throw new Error(`argon2id memoryKiB must be an integer \u2265 8, got ${memoryKiB}`);
  }
  if (!Number.isInteger(iterations) || iterations < 1) {
    throw new Error(`argon2id iterations must be a positive integer, got ${iterations}`);
  }
  if (!Number.isInteger(parallelism) || parallelism < 1 || parallelism > 255) {
    throw new Error(`argon2id parallelism must be an integer in [1, 255], got ${parallelism}`);
  }
  if (!Number.isInteger(keyLength) || keyLength !== KDF_KEY_LENGTH) {
    throw new Error(
      `argon2id keyLength must be ${KDF_KEY_LENGTH} (AES-256 requires a 32-byte key), got ${keyLength}`
    );
  }
}
function deriveKeyScrypt(passphrase, salt, params = DEFAULT_SCRYPT_PARAMS) {
  if (typeof passphrase !== "string") {
    throw new Error("passphrase must be a string");
  }
  if (passphrase.length === 0) {
    throw new Error("passphrase must not be empty");
  }
  if (!(salt instanceof Uint8Array) || salt.length < 8) {
    throw new Error(
      `salt must be a Uint8Array of at least 8 bytes, got ${salt?.length ?? "non-buffer"}`
    );
  }
  validateScryptParams(params);
  return scryptSync(passphrase, Buffer.from(salt), params.keyLength, {
    N: params.N,
    r: params.r,
    p: params.p,
    maxmem: params.maxmem
  });
}
function deriveKeyArgon2id(passphrase, salt, params = DEFAULT_ARGON2ID_PARAMS) {
  if (typeof passphrase !== "string") {
    throw new Error("passphrase must be a string");
  }
  if (passphrase.length === 0) {
    throw new Error("passphrase must not be empty");
  }
  if (!(salt instanceof Uint8Array) || salt.length < 8) {
    throw new Error(
      `salt must be a Uint8Array of at least 8 bytes, got ${salt?.length ?? "non-buffer"}`
    );
  }
  validateArgon2idParams(params);
  const { Algorithm, Version, hashRawSync } = loadArgon2Runtime();
  return hashRawSync(passphrase, {
    algorithm: Algorithm.Argon2id,
    version: Version.V0x13,
    memoryCost: params.memoryKiB,
    timeCost: params.iterations,
    parallelism: params.parallelism,
    outputLen: params.keyLength,
    salt
  });
}
function deriveKey(algorithm, passphrase, salt, params) {
  if (algorithm === "scrypt") {
    return deriveKeyScrypt(passphrase, salt, params);
  }
  if (algorithm === "argon2id") {
    return deriveKeyArgon2id(passphrase, salt, params);
  }
  throw new Error(`unknown KDF algorithm: ${algorithm}`);
}
function constantTimeEqual(a, b) {
  if (a.length !== b.length) {
    return false;
  }
  return timingSafeEqual(Buffer.from(a), Buffer.from(b));
}

export {
  DEFAULT_SCRYPT_PARAMS,
  DEFAULT_ARGON2ID_PARAMS,
  KDF_SALT_LENGTH,
  KDF_KEY_LENGTH,
  validateScryptParams,
  validateArgon2idParams,
  deriveKeyScrypt,
  deriveKeyArgon2id,
  deriveKey,
  constantTimeEqual
};
//# sourceMappingURL=chunk-FP2373TW.js.map