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