# Argon2id wrapper _(no submodules)_ ## Purpose `argon2id.ts` is the OWASP-grade Argon2id derivation entry point for `@suaveplan/crypto-vault`. It wraps `@suaveplan/crypto-hash`'s primitive `argon2id` with two enterprise concerns the primitive itself does not enforce: an OWASP-safe parameter floor (memoryKB ≥ 64 MiB, iterations ≥ 3, parallelism ≥ 1) and a hard ceiling (memoryKB ≤ 1 GiB, outputLength ≤ 4 KiB) that prevents accidental denial-of-service from misconfigured callers. ## Features - `assertSafeArgon2idParams(params)` — pure validator usable in tests, in config validation, and as a precondition for any Argon2id call. - `deriveKeyWithArgon2id(password, salt, params?, options?)` — full derivation pipeline with telemetry recording and structured errors. - `DEFAULT_ARGON2ID_PARAMS` — frozen `{ memoryKB: 65536, iterations: 3, parallelism: 4, outputLength: 32 }` constant. - `OWASP_MIN_*` and `ARGON2ID_MAX_*` exported constants for callers that build their own parameter UI. ## Usage: Basic Example ```ts import { DEFAULT_ARGON2ID_PARAMS, deriveKeyWithArgon2id, } from "@suaveplan/crypto-vault/argon2id/argon2id"; const password = new TextEncoder().encode("correct horse battery staple"); const salt = crypto.getRandomValues(new Uint8Array(16)); const key = await deriveKeyWithArgon2id(password, salt, DEFAULT_ARGON2ID_PARAMS); console.log(key.length); // 32 ``` ## Usage: Advanced Example ```ts import { assertSafeArgon2idParams, deriveKeyWithArgon2id, } from "@suaveplan/crypto-vault/argon2id/argon2id"; import type { Argon2idParams } from "@suaveplan/crypto-vault/types"; // Stronger profile for highly sensitive accounts. const strict: Argon2idParams = { memoryKB: 131_072, // 128 MiB iterations: 4, parallelism: 4, outputLength: 64, }; assertSafeArgon2idParams(strict); // throws if any cell breaks the bands const password = new TextEncoder().encode("super-strong-passphrase"); const salt = crypto.getRandomValues(new Uint8Array(16)); const key = await deriveKeyWithArgon2id(password, salt, strict, { clock: () => 0, // deterministic telemetry timestamps for tests }); console.log(key.length); // 64 ``` ## API Reference ### `deriveKeyWithArgon2id(password, salt, params?, options?)` - `password: Uint8Array` — must be non-empty. - `salt: Uint8Array` — must be non-empty (16+ bytes recommended). - `params: Argon2idParams = DEFAULT_ARGON2ID_PARAMS` — validated through `assertSafeArgon2idParams`. - `options.clock?: () => number` — wall-clock source for the duration histogram. Returns `Promise` of length `params.outputLength`. Throws `CryptoVaultError`: - `ARGON2ID.INVALID_INPUT` for empty `password` or `salt`. - `ARGON2ID.UNSAFE_PARAMETERS` for parameters outside the OWASP / hard-cap bands. ### `assertSafeArgon2idParams(params)` Throws `CryptoVaultError(ARGON2ID.UNSAFE_PARAMETERS)` when any of these conditions are violated: - `memoryKB` integer in `[OWASP_MIN_MEMORY_KB, ARGON2ID_MAX_MEMORY_KB]`. - `iterations` integer ≥ `OWASP_MIN_ITERATIONS`. - `parallelism` integer ≥ `OWASP_MIN_PARALLELISM`. - `outputLength` integer in `(0, ARGON2ID_MAX_OUTPUT_LENGTH]`. ### Constants - `OWASP_MIN_MEMORY_KB = 65_536` - `OWASP_MIN_ITERATIONS = 3` - `OWASP_MIN_PARALLELISM = 1` - `ARGON2ID_MAX_MEMORY_KB = 1_048_576` - `ARGON2ID_MAX_OUTPUT_LENGTH = 4_096` - `DEFAULT_ARGON2ID_PARAMS` — frozen object. ## Implementation Notes - The underlying primitive is sync (noble's `@noble/hashes/argon2`); the wrapper exposes `Promise` to keep the public API stable against future native or worker-backed implementations. - The OWASP minimums encode the November 2024 password storage cheat sheet guidance for Argon2id (m=64MiB, t=3, p=1+). - The hard cap on memory cost (1 GiB) and output length (4 KiB) defends against caller bugs and denial-of-service-by-misconfiguration. A caller that legitimately needs more should open a follow-up change rather than bypass the guard. - Telemetry timing comes from the injected (or default) clock, not `performance.now()`; this keeps the histogram reproducible under tests.