Files
suaveplan/openspec/archive/2026-04-19-crypto-primitive-replaceability/specs/crypto-utils/spec.md
2026-05-27 23:29:53 +01:00

3.5 KiB

ADDED Requirements

Requirement: Pure-composition utility surface

@suaveplan/crypto-utils SHALL expose encoding, byte, constant-time, and test-harness utilities that are safe to author from scratch (no field arithmetic, no secret-data side channels beyond constant-time equality).

Scenario: Encoding utilities available

  • WHEN a consumer imports from @suaveplan/crypto-utils
  • THEN hex, base64, base64url, base58 encoders/decoders are exported, each with encode(bytes): string and decode(text): Uint8Array
  • AND decoders throw a SuaveplanError subclass with stable code CRYPTO.UTILS.INVALID_ENCODING on malformed input

Scenario: Byte utilities available

  • WHEN a consumer imports from @suaveplan/crypto-utils
  • THEN concatBytes(...arrays: Uint8Array[]): Uint8Array, xor(a: Uint8Array, b: Uint8Array): Uint8Array, i2osp(n: bigint, len: number): Uint8Array, os2ip(bytes: Uint8Array): bigint are exported

Scenario: Constant-time, random, and zeroize utilities available

  • WHEN a consumer imports from @suaveplan/crypto-utils
  • THEN constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean is exported and implemented without early return
  • AND randomBytes(n: number): Uint8Array is exported, sourcing from globalThis.crypto.getRandomValues
  • AND zeroize(bytes: Uint8Array): void is exported

Requirement: Test-vector and fuzz harness

@suaveplan/crypto-utils SHALL expose harness functions that crypto-hash, crypto-curve, and crypto-cipher use to run KATs and differential fuzz against their primitive impls.

Scenario: KAT harness

  • WHEN a primitive test imports runVectors from @suaveplan/crypto-utils/testing
  • THEN it can pass a vector list and a set of impls, and receive a per-impl pass/fail/pending report
  • AND pending impls (throwing PrimitiveNotImplemented) are distinguished from failing impls

Scenario: Differential fuzz harness

  • WHEN a primitive test imports diffFuzz from @suaveplan/crypto-utils/testing
  • THEN it can pass two impls, an input generator, and an iteration count, and receive a mismatch report
  • AND any byte-level divergence in outputs is reported with the reproducing input

Requirement: Primitive id registry

@suaveplan/crypto-utils SHALL export the PrimitiveId union type enumerating every hash, curve, and AEAD primitive across the crypto family, and a PRIMITIVE_IDS const array for runtime iteration.

Scenario: Registry available

  • WHEN a consumer imports PrimitiveId and PRIMITIVE_IDS from @suaveplan/crypto-utils/primitive-id
  • THEN PRIMITIVE_IDS contains every id supported by crypto-hash, crypto-curve, and crypto-cipher
  • AND PrimitiveId narrows to the same union at compile time

Requirement: No vendored code

@suaveplan/crypto-utils SHALL contain only original code authored in this monorepo. No src/vendored/ directory.

Scenario: No vendored directory

  • WHEN the package tree is inspected
  • THEN no path matches packages/universal/crypto-utils/src/vendored/**

Requirement: Merkle helpers

@suaveplan/crypto-utils SHALL expose Merkle tree construction and inclusion-proof helpers generic over any hash primitive from @suaveplan/crypto-hash.

Scenario: Merkle helpers available

  • WHEN a consumer imports merkleRoot and merkleProof from @suaveplan/crypto-utils/merkle
  • THEN they accept a hash function parameter and a list of leaves, returning a root and an inclusion proof respectively