WebCrypto-backed HKDF deriveBits/deriveKey wrapping crypto.subtle (RFC 5869).
Module webcryptoHkdf | Source packages/front/fw/src/crypto/webcrypto/hkdf.js | Deps none | Worker-safe yes
Performs HKDF key derivation (RFC 5869) via crypto.subtle: imports the IKM
as an HKDF base key, then calls deriveBits or deriveKey. Combined
extract+expand only — WebCrypto does not expose the separate HKDF-Extract and
HKDF-Expand primitives. Opt-in alternative to the pure-JS hkdf module.
Supported hashes: 'SHA-1', 'SHA-256' (default), 'SHA-384', 'SHA-512'.
SHA-3 and other hashes are not supported by the WebCrypto API.
Resolve
const h = runtime.resolve('webcryptoHkdf');
// Returns: { isAvailable, deriveBits, deriveKey }
API
| Method | Signature | Returns |
|---|---|---|
isAvailable |
() => boolean |
true when crypto.subtle is present. |
deriveBits |
(ikm, salt, info, lengthBits, hash?) => Promise<Uint8Array|false> |
Derived key material as bytes, or false on error. |
deriveKey |
(ikm, salt, info, derivedKeyAlg, usages, hash?, extractable?) => Promise<CryptoKey|false> |
A CryptoKey ready to use, or false on error. |
Parameters
deriveBits(ikm, salt, info, lengthBits, hash?)
| Parameter | Type | Description |
|---|---|---|
ikm |
Uint8Array |
Input keying material. |
salt |
Uint8Array |
Salt value. Empty Uint8Array is valid (RFC 5869 §2.2 treats it as a block of zeros). |
info |
Uint8Array |
Context / application-specific information. May be empty. |
lengthBits |
number |
Number of bits to derive. Must be a positive multiple of 8. |
hash |
HashName? |
Hash algorithm. Default: 'SHA-256'. |
deriveKey(ikm, salt, info, derivedKeyAlg, usages, hash?, extractable?)
| Parameter | Type | Description |
|---|---|---|
ikm |
Uint8Array |
Input keying material. |
salt |
Uint8Array |
Salt value. |
info |
Uint8Array |
Context information. |
derivedKeyAlg |
object |
WebCrypto key-algorithm descriptor (e.g. {name:'AES-GCM',length:256}). |
usages |
KeyUsage[] |
Key usage array (e.g. ['encrypt','decrypt']). |
hash |
HashName? |
Hash algorithm. Default: 'SHA-256'. |
extractable |
boolean? |
Whether the derived key is extractable. Default: false. |
Error behavior (no-throw contract)
All methods resolve to false (never reject) when:
crypto.subtleis unavailable — logs[crypto] NOT READY.hashis not in the supported set — logs[crypto] INVALID.lengthBitsis not a positive multiple of 8 — logs[crypto] INVALID.crypto.subtlerejects — logs[crypto] FAIL.
Examples
Derive raw key material (RFC 5869 Test Case 1)
const h = runtime.resolve('webcryptoHkdf');
const ikm = new Uint8Array([0x0b, 0x0b, /* … 22 bytes */]);
const salt = new Uint8Array([0x00, 0x01, 0x02, /* … */]);
const info = new Uint8Array([0xf0, 0xf1, /* … */]);
const okm = await h.deriveBits(ikm, salt, info, 336); // 42 bytes
// okm: Uint8Array(42) — matches RFC 5869 A.1 expected OKM
Derive an AES-GCM key
const aesKey = await h.deriveKey(
ikm, salt, info,
{ name: 'AES-GCM', length: 256 },
['encrypt', 'decrypt'],
'SHA-256'
);
// aesKey: CryptoKey { type: 'secret', algorithm: { name: 'AES-GCM', … } }
const ct = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, aesKey, plaintext);
Derive with empty salt and info
// RFC 5869 §2.2: empty salt is treated as HashLen zeros internally
const okm = await h.deriveBits(ikm, new Uint8Array(0), new Uint8Array(0), 336);
Worker usage
const worker = fw.createWorker(
async function ({ libs, args }) {
const okm = await libs.webcryptoHkdf.deriveBits(
args.ikm, args.salt, args.info, 256
);
self.postMessage(okm);
},
{ dependencies: ['webcryptoHkdf'], args: { ikm, salt, info } }
);
Notes
- Combined extract+expand only: WebCrypto HKDF does not expose the extract
and expand stages separately. Use the pure-JS
hkdfmodule when you need access to the intermediate PRK or per-component operations. - SHA-3 not supported: WebCrypto mandates SHA-1/256/384/512 only.
For HMAC-SHA-3 or BLAKE2b-based HKDF, use the pure-JS
hkdfmodule. - Zero-length salt: RFC 5869 §2.2 specifies that a missing/empty salt is
treated as a string of HashLen zero bytes.
crypto.subtleimplements this correctly — passnew Uint8Array(0). - OKM length limit: RFC 5869 §2.3 limits output to
255 × HashLenbytes. Violations are rejected bycrypto.subtle(resolves tofalse). - Availability: call
isAvailable()before use in environments wherecrypto.subtlemay be absent (e.g.http:pages, older Node.js without thewebcryptoflag).
See also
- hkdf — pure-JS HKDF (extract+expand separately, bitArray I/O)
- webcryptoPbkdf2 — WebCrypto PBKDF2 (password-based KDF)
- webcryptoHmac — WebCrypto HMAC
- webcryptoDigest — WebCrypto SHA-256/384/512/1 digests