4.1 KiB
4.1 KiB
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_*andARGON2ID_MAX_*exported constants for callers that build their own parameter UI.
Usage: Basic Example
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
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 throughassertSafeArgon2idParams.options.clock?: () => number— wall-clock source for the duration histogram.
Returns Promise<Uint8Array> of length params.outputLength.
Throws CryptoVaultError:
ARGON2ID.INVALID_INPUTfor emptypasswordorsalt.ARGON2ID.UNSAFE_PARAMETERSfor parameters outside the OWASP / hard-cap bands.
assertSafeArgon2idParams(params)
Throws CryptoVaultError(ARGON2ID.UNSAFE_PARAMETERS) when any of these
conditions are violated:
memoryKBinteger in[OWASP_MIN_MEMORY_KB, ARGON2ID_MAX_MEMORY_KB].iterationsinteger ≥OWASP_MIN_ITERATIONS.parallelisminteger ≥OWASP_MIN_PARALLELISM.outputLengthinteger in(0, ARGON2ID_MAX_OUTPUT_LENGTH].
Constants
OWASP_MIN_MEMORY_KB = 65_536OWASP_MIN_ITERATIONS = 3OWASP_MIN_PARALLELISM = 1ARGON2ID_MAX_MEMORY_KB = 1_048_576ARGON2ID_MAX_OUTPUT_LENGTH = 4_096DEFAULT_ARGON2ID_PARAMS— frozen object.
Implementation Notes
- The underlying primitive is sync (noble's
@noble/hashes/argon2); the wrapper exposesPromise<Uint8Array>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.