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,96 @@
# hkdf.select
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`hkdf.select.ts` is the build-time primitive selector for the HKDF implementation in `@suaveplan/crypto-hash`. It re-exports exactly one concrete backend — either `hkdf.noble.ts` (backed by `@noble/hashes`) or `hkdf.native.ts` — depending on the `hkdf` field in `crypto.config.ts`.
HKDF (HMAC-based Extract-and-Expand Key Derivation Function, RFC 5869) is the standard KDF for deriving multiple independent keys from a single input keying material (IKM) such as a Diffie-Hellman shared secret or a session master secret. This selector exposes the `hkdf` function, `HkdfAlgorithm`, and `HkdfOptions` through a stable interface.
## Features
- Re-exports `hkdf(algo, ikm, options)`, `HkdfAlgorithm`, and `HkdfOptions`.
- Generated by `bun scripts/gen-crypto-selects.ts` — never hand-edited.
- Controlled by `crypto.config.ts`: set `hkdf` to `'noble'` or `'native'`.
- Supports SHA-256, SHA-384, and SHA-512 as the underlying PRF.
- `HkdfOptions` carries `salt`, `info`, and `length` for Extract and Expand phases.
## Usage: Basic Example
```ts
import { hkdf } from "@suaveplan/crypto-hash/primitives/hkdf/hkdf";
const ikm = new Uint8Array(32).fill(0xff);
const key = hkdf("SHA-256", ikm, {
salt: new Uint8Array(32),
info: new TextEncoder().encode("session-key"),
length: 32,
});
console.log(key.length); // 32
```
## Usage: Advanced Example
```ts
import { hkdf, type HkdfAlgorithm } from "@suaveplan/crypto-hash/primitives/hkdf/hkdf";
// Derive two independent sub-keys from one shared secret (X25519 output).
function deriveKeys(sharedSecret: Uint8Array, salt: Uint8Array): {
encKey: Uint8Array;
authKey: Uint8Array;
} {
const enc = new TextEncoder();
return {
encKey: hkdf("SHA-256", sharedSecret, {
salt,
info: enc.encode("enc-key"),
length: 32,
}),
authKey: hkdf("SHA-256", sharedSecret, {
salt,
info: enc.encode("auth-key"),
length: 32,
}),
};
}
```
## API Reference
Re-exports the following from the active implementation:
### `hkdf(algo: HkdfAlgorithm, ikm: Uint8Array, options: HkdfOptions): Uint8Array`
Runs HKDF Extract followed by HKDF Expand.
| Parameter | Type | Description |
|-----------|------|-------------|
| `algo` | `HkdfAlgorithm` | Hash algorithm for the internal HMAC. |
| `ikm` | `Uint8Array` | Input keying material. |
| `options.salt` | `Uint8Array` | Optional but strongly recommended random salt. |
| `options.info` | `Uint8Array` | Context/application-specific binding string. |
| `options.length` | `number` | Output length in bytes (max 255 × hash output length). |
**Returns:** Derived key material of `options.length` bytes.
### `HkdfAlgorithm`
```ts
type HkdfAlgorithm = "SHA-256" | "SHA-384" | "SHA-512";
```
### `HkdfOptions`
```ts
interface HkdfOptions {
readonly salt: Uint8Array;
readonly info: Uint8Array;
readonly length: number;
}
```
## Implementation Notes
HKDF is a two-step process. Extract collapses potentially non-uniform IKM into a pseudorandom key (PRK) using HMAC with the salt. Expand stretches PRK into the requested number of output bytes by iterating HMAC with the info string. Noble's `hkdf` function implements RFC 5869 §2 exactly, including the `0x01`, `0x02`, … counter suffixes in the Expand loop. The `length` maximum per RFC 5869 is `255 * HashLen`; violations will cause Noble to throw, which propagates up without wrapping here — validation at the public KDF façade should guard against this before reaching the primitive. The native stub throws `PrimitiveNotImplemented("hkdf")`.