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,76 @@
# hmac.select
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`hmac.select.ts` is the build-time primitive selector for the HMAC implementation within `@suaveplan/crypto-hash`. It re-exports exactly one concrete backend — either `hmac.noble.ts` (backed by `@noble/hashes`) or `hmac.native.ts` — according to the `hmac` entry in `crypto.config.ts`.
HMAC (Hash-based Message Authentication Code, RFC 2104) is the standard construction for producing a keyed digest from an arbitrary hash function. This selector exposes a single `hmac` function and the `HmacAlgorithm` type, providing a consistent interface regardless of which backend is active.
## Features
- Single-symbol re-export of `hmac(algo, key, data)` and `HmacAlgorithm`.
- Generated by `bun scripts/gen-crypto-selects.ts` — never hand-edited.
- Controlled by `crypto.config.ts`: set `hmac` to `'noble'` or `'native'`.
- Supports `"SHA-256"`, `"SHA-384"`, and `"SHA-512"` hash algorithms.
- Maintains a stable public API across backend switches.
## Usage: Basic Example
```ts
import { hmac } from "@suaveplan/crypto-hash/primitives/hmac/hmac";
const key = new Uint8Array(32).fill(0xab);
const data = new TextEncoder().encode("authenticate me");
const tag = hmac("SHA-256", key, data);
console.log(tag.length); // 32
```
## Usage: Advanced Example
```ts
import { hmac, type HmacAlgorithm } from "@suaveplan/crypto-hash/primitives/hmac/hmac";
// Verify a webhook signature from an untrusted header.
function verifyWebhookSignature(
algo: HmacAlgorithm,
secret: Uint8Array,
body: Uint8Array,
expected: Uint8Array
): boolean {
const computed = hmac(algo, secret, body);
// Constant-time comparison avoids timing side-channels.
if (computed.length !== expected.length) return false;
let diff = 0;
for (let i = 0; i < computed.length; i++) diff |= computed[i] ^ expected[i];
return diff === 0;
}
```
## API Reference
Re-exports the following from the active implementation:
### `hmac(algo: HmacAlgorithm, key: Uint8Array, data: Uint8Array): Uint8Array`
Computes HMAC over `data` with `key` using the specified hash algorithm.
| Parameter | Type | Description |
|-----------|------|-------------|
| `algo` | `HmacAlgorithm` | `"SHA-256"`, `"SHA-384"`, or `"SHA-512"`. |
| `key` | `Uint8Array` | Secret key bytes (any length). |
| `data` | `Uint8Array` | Message to authenticate. |
**Returns:** HMAC tag — 32 bytes for SHA-256, 48 for SHA-384, 64 for SHA-512.
### `HmacAlgorithm`
```ts
type HmacAlgorithm = "SHA-256" | "SHA-384" | "SHA-512";
```
## Implementation Notes
HMAC is defined as `H(K XOR opad || H(K XOR ipad || message))`. The Noble backend calls `@noble/hashes/hmac` directly, which implements this construction on top of the same audited SHA-2 primitives used by the standalone hash functions. Key padding and the inner/outer hash passes are handled internally. RFC 2202 (SHA-256) and RFC 4231 (SHA-384/512) test vectors pass in the test suite. The native stub throws `PrimitiveNotImplemented("hmac")` and will be activated in Phase 3 after per-primitive audit.