import { argon2id } from "hash-wasm"; // Argon2id params: m=65536 KiB (64 MiB), t=3, p=4, 32-byte output. // Meets the OWASP "password manager" tier (m=65536, t=3, p=1) and exceeds it // on parallelism. Changing any of these changes the derived key — existing // vaults on disk can only be unlocked with the params they were sealed under. // Raising them tightens attacker cost; lowering them is a regression. export async function deriveKey( password: string, salt: Uint8Array ): Promise { const result = await argon2id({ password, salt, parallelism: 4, iterations: 3, memorySize: 65536, hashLength: 32, outputType: "binary", }); return result; } // Per-vault salt: 16 bytes from the OS CSPRNG. A fresh salt is generated at // vault creation and on every changePassword. Prevents cross-user // precomputation attacks against the same master passphrase. export function generateSalt(): Uint8Array { return crypto.getRandomValues(new Uint8Array(16)); }