first commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user