HKDF (RFC 5869 / SP 800-56C Rev. 2) — extract-then-expand KDF based on HMAC.

Module hkdf | Source packages/front/fw/src/crypto/hash/hkdf.js | Deps bitArray, utf8, hmac | Worker-safe yes

Polymorphic on HMAC: default = HMAC-SHA-256; pass an hmac instance built over another hash for other families.

Resolve

const hkdf = runtime.resolve('hkdf');
// Returns: { extract, expand, derive }

API

Method Signature Returns
extract (salt, ikm, Prff?) => bitArray PRK = HMAC-Hash(salt, IKM)
expand (prk, info, lengthBits, Prff?) => bitArray | false OKM truncated to lengthBits
derive (salt, ikm, info, lengthBits, Prff?) => bitArray | false One-shot extract + expand

Prff is an hmac module instance (default = HMAC-SHA-256). For HMAC-SHA-512: hmac.factory(bitArray, utf8, sha512).

Examples

One-shot

const { hkdf } = fw.runtime.resolveAll(['hkdf']);

const okm = hkdf.derive(
    bitArray.ui8_to_ba(salt),
    bitArray.ui8_to_ba(ikm),
    bitArray.ui8_to_ba(new TextEncoder().encode('app-context-v1')),
    256                                          // bits requested
);

Cr2 hybrid (post-quantum)

// SP 800-56C Rev. 2 §5.8.2: IKM = Z || T (classical || PQ)
const Z = ml_kem768.decapsulate(...);            // 32 bytes
const T = ecdh_p256.derive(...);                 // 32 bytes
const ikm = bitArray.concat(Z, T);
const okm = hkdf.derive(salt, ikm, info, 256);

Worker Usage

const worker = fw.createWorker(
    function ({ libs, args }) {
        const okm = libs.hkdf.derive(args[0], args[1], args[2], 256);
        self.postMessage(okm);
    },
    { dependencies: ['hkdf'], args: [salt, ikm, info] }
);

Notes

  • OKM limit: lengthBits / hashBits ≤ 255 (RFC 5869 §2.3). Otherwise false + console.warn('INVALID').
  • Empty salt = treated as HashLen zero bytes (RFC 5869 §2.2).
  • Cr2 hybrid + multi-expand: Cr2 single = extract(Z||T); multi-expand = 1 shared PRK + N distinct expand iterations (TLS-style multi-key derivation).

See also