Files
2026-05-27 23:29:53 +01:00

3.7 KiB

Capability: hash-primitives

ADDED Requirements

Package identity

  • REQ-HASH-001: Package name is @suaveplan/hash, located at packages/universal/hash.
  • REQ-HASH-002: Runtime deps: @noble/hashes, @suaveplan/error, tslib, zod. Zero browser/React/Node-only deps.
  • REQ-HASH-003: Ships "sideEffects": false. All modules are individually subpath-exported for tree-shaking.

Hash digests

  • REQ-HASH-010: Exports sha256(data: Uint8Array): Uint8Array — 32-byte SHA-256 digest.
  • REQ-HASH-011: Exports sha384(data: Uint8Array): Uint8Array — 48-byte SHA-384 digest.
  • REQ-HASH-012: Exports sha512(data: Uint8Array): Uint8Array — 64-byte SHA-512 digest.
  • REQ-HASH-013: Exports HashAlgorithm = "SHA-256" | "SHA-384" | "SHA-512".
  • REQ-HASH-014: Exports hash(algo: HashAlgorithm, data: Uint8Array): Uint8Array — algorithm dispatcher.

HMAC

  • REQ-HASH-020: Exports hmac(algo: HashAlgorithm, key: Uint8Array, data: Uint8Array): Uint8Array.
  • REQ-HASH-021: Empty key is permitted (library-level; policy enforcement is the caller's responsibility).

HKDF

  • REQ-HASH-030: Exports hkdf(algo: HashAlgorithm, ikm: Uint8Array, options: HkdfOptions): Uint8Array.
  • REQ-HASH-031: HkdfOptions = { salt: Uint8Array; info: Uint8Array; length: number }. All fields required.
  • REQ-HASH-032: Throws HashError("HASH.KDF.INVALID_PARAMS") if length <= 0 or length > 255 * hashLen.

PBKDF2

  • REQ-HASH-040: Exports pbkdf2(algo: HashAlgorithm, password: Uint8Array, options: Pbkdf2Options): Uint8Array.
  • REQ-HASH-041: Pbkdf2Options = { salt: Uint8Array; iterations: number; length: number }.
  • REQ-HASH-042: Throws HashError("HASH.KDF.INVALID_PARAMS") if iterations < 600_000 (OWASP 2023 minimum for SHA-256). Same minimum for SHA-384/512 (conservative — these are also interactive-login strength minimums).
  • REQ-HASH-043: Exports PBKDF2_MIN_ITERATIONS = 600_000.

Argon2id

  • REQ-HASH-050: Exports argon2id(password: Uint8Array, options: Argon2idOptions): Uint8Array.
  • REQ-HASH-051: Argon2idOptions = { salt: Uint8Array; timeCost: number; memoryCost: number; parallelism: number; length: number }.
  • REQ-HASH-052: Throws HashError("HASH.KDF.INVALID_PARAMS") per-field: timeCost < 1, memoryCost < 8, parallelism < 1, length <= 0. Each error's context includes { field, value, minimum }.
  • REQ-HASH-053: Exports ARGON2ID_MIN_MEMORY_COST_KIB = 8, ARGON2ID_MIN_TIME_COST = 1, ARGON2ID_MIN_PARALLELISM = 1.

Encoding utilities

  • REQ-HASH-060: Exports toHex(bytes: Uint8Array): string and fromHex(hex: string): Uint8Array.
  • REQ-HASH-061: Exports toBase64(bytes: Uint8Array): string, fromBase64(b64: string): Uint8Array, toBase64Url(bytes: Uint8Array): string, fromBase64Url(b64url: string): Uint8Array.
  • REQ-HASH-062: fromHex/fromBase64/fromBase64Url throw HashError("HASH.ENCODING.INVALID_INPUT") on malformed input.

Error surface

  • REQ-HASH-070: Exports HashError extends SuaveplanError<HashCode>.
  • REQ-HASH-071: Error codes namespace: HASH.KDF.INVALID_PARAMS, HASH.ALGORITHM.UNSUPPORTED, HASH.ENCODING.INVALID_INPUT.
  • REQ-HASH-072: No error message or context field contains raw key material or password bytes.

Quality

  • REQ-HASH-080: 100% statement + branch coverage (istanbul).
  • REQ-HASH-081: fast-check property tests: determinism (same input → same output), HMAC known-vector (RFC 4231 vectors).
  • REQ-HASH-082: mitata benchmarks: sha256/sha384/sha512 at 1 KiB and 1 MiB; argon2id at minimum params.
  • REQ-HASH-083: Every .ts implementation file has a sibling .md (≥200 words).
  • REQ-HASH-084: tests/no-disallowed.test.ts asserts no Math.random, Date.now, or crypto.getRandomValues in src/.