first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
# `AlgorithmRegistry`
## Purpose
In-package mapping from `alg` identifier to the concrete `AlgorithmImpl` that knows how to verify and (optionally) sign. The registry is seeded at module load with the 13 built-in algorithms required by RFC 7518 §3 and RFC 8037 (`HS256/384/512`, `RS256/384/512`, `PS256/384/512`, `ES256/384/512`, `EdDSA`, `none`). Downstream packages register experimental algorithms (e.g. ML-DSA, secp256k1) via `AlgorithmRegistry.register` without forking this package.
## Features
- `defaultRegistry` — the package-wide seeded registry consumed by the verify/sign pipelines.
- `register(alg, impl)` — add an algorithm; duplicate registration throws `JWS.ALG_UNSUPPORTED`.
- `lookup(alg)` — returns the impl or `undefined`.
- `lookupOrThrow(alg)` — returns the impl or throws `JWS.ALG_UNSUPPORTED`.
- `has(alg)` / `algorithms()` — introspection helpers.
## Usage: Basic Example
```ts
import { defaultRegistry } from "@suaveplan/jws";
defaultRegistry.has("RS256"); // true
defaultRegistry.has("ML-DSA-44"); // false
```
## Usage: Advanced Example
```ts
import {
AlgorithmRegistry,
type AlgorithmImpl,
defaultRegistry,
} from "@suaveplan/jws";
const mlDsa44: AlgorithmImpl<Uint8Array> = {
alg: "ML-DSA-44",
verify: async (signingInput, sig, pub) => myMlDsaImpl.verify(pub, sig, signingInput),
sign: async (signingInput, priv) => myMlDsaImpl.sign(priv, signingInput),
};
defaultRegistry.register("ML-DSA-44", mlDsa44);
// Or build an isolated registry for an integration test:
const isolated = new AlgorithmRegistry();
isolated.register("HS256", myHsImpl);
```
## API Reference
- `class AlgorithmRegistry`
- `register<K>(alg: string, impl: AlgorithmImpl<K>): void`
- `lookup(alg: string): AlgorithmImpl<unknown> | undefined`
- `lookupOrThrow(alg: string): AlgorithmImpl<unknown>`
- `has(alg: string): boolean`
- `algorithms(): readonly string[]`
- `const defaultRegistry: AlgorithmRegistry`
- `interface AlgorithmImpl<K = unknown> { alg: string; verify(signingInput, signature, key: K): Promise<boolean>; sign?(signingInput, key: K): Promise<Uint8Array> }`
- `seedBuiltinAlgorithms(): void` — idempotent seeding (already invoked at module load).
## Implementation Notes
Built-ins are seeded by the side-effect import `import "./builtin.js"` at the root of `algorithms/index.ts` AND `src/index.ts`. Idempotent via a module-scoped boolean so the registry survives test reload cycles. Registering an algorithm twice throws rather than silently overwriting, because silent overwrite would be an algorithm-confusion vector — a malicious downstream package could redefine `RS256` to delegate to an attacker-controlled impl. The registry is mutable but only via `register`; there is no `unregister` for the same reason.