[](https://www.npmjs.com/package/futoin-hkdf) [](https://www.npmjs.com/package/futoin-hkdf) [](https://www.npmjs.com/package/futoin-hkdf) [](https://nodei.co/npm/futoin-hkdf/) # About Node.js implementation of [RFC5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF)](https://tools.ietf.org/html/rfc5869). Additionally, it supports a `HKDF-Expand-Label` variation based on [RFC8446: The Transport Layer Security (TLS) Protocol Version 1.3, section 7.1. Key Schedule](https://datatracker.ietf.org/doc/html/rfc8446#section-7.1). The implementation is fully compliant with test vectors provided in the RFC. There are alternative modules, but they are: * much less performing and/or * have quite poor code quality at the moment and/or * are not compliant with RFC (e.g. work only with string parameters) and/or * not working with current Node.js versions and/or * do not support arbitrary hash functions and/or * not reliable dependency for FutoIn™ Security concept in general. Standalone HKDF `extract()` and `expand()` actions are also available for advanced usage. **Documentation** --> [FutoIn™ Guide](https://futoin.org/docs/miscjs/hkdf/) Author: [Andrey Galkin](mailto:andrey@futoin.org) # Performance comparison The figures in "derived keys per second". * **futoin-hkdf** - **74 642** - fully compliant * `node-hdkf`/`hdkf` modules - *57 707* (~22% slower) - seems to be broken by design - **produces wrong results with RFC test vectors** * `ctrlpanel-hdkf` - *52 181* (~30% slower) - seems to be compliant * `@stablelib/hkdf` - *39 808* (~46% slower) - seems to be compliant # Installation for Node.js Command line: ```sh $ npm install futoin-hkdf --save ``` or: ```sh $ yarn add futoin-hkdf --save ``` # Examples ```javascript const hkdf = require('futoin-hkdf'); // Parameter overview //------------------- // initial keying material const ikm = 'string-or-buffer'; // required output length in bytes const length = 16; // can be empty string or false equivalent const salt = 'strongly-encouraged'; // optional parameter const info = 'optional-context'; // HMAC hashing algorithm to use const hash = 'SHA-256'; // Generic derivation //------------------- hkdf(ikm, length, {salt, info, hash}); // Buffer(length) - derived key hkdf(ikm, length, {salt, info, hash}).toString('hex'); // String(2*length) // NOTE: all optional paramaters are passed in object // With some parameters omitted //------------------- hkdf(ikm, length, {salt}); hkdf(ikm, length, {info}); hkdf(ikm, length, {hash}); hkdf(ikm, length); // Advanced usage (only if you know what you are doing) //------------------- // As in underlying Node.js crypto library const lhash = hash.toLowerCase().replace( '-', '' ); // 'sha256' hkdf.hash_length(lhash); // get hash_len hkdf.extract(lhash, hash_len, ikm, salt); // run only step #1 hkdf.expand(lhash, hash_len, prk, length, info); // run only step #2 // TLS v1.3+ //------------------- const hkdf_tls = require('futoin-hkdf/tls'); const label = 'tls13 ...'; const context = Buffer.from( /* E.g some binary hash generation */ '' ); hkdf_tls(ikm, length, {salt, label, context, hash}); // Buffer(length) - derived key // Advanced usage hkdf_tls.expand_label(lhash, hash_len, prk, length, label, context); // Same as: hkdf.expand(lhash, hash_len, prk, length, hkdf_tls.info(length, label, context)); ``` # API documentation ## Functions
BufferHMAC-based Extract-and-Expand Key Derivation Function (HKDF)
BufferTLS v1.3 HKDF-extract + HKFD-Expand-Label action
Buffer
HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
**Kind**: global function
**Returns**: Buffer - Raw buffer with derived key of @p length bytes
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| ikm | Buffer \| string | | Initial Keying Material |
| length | integer | | Required byte length of output |
| salt | Buffer \| string | '' | Optional salt (recommended) |
| info | Buffer \| string | '' | Optional context (safe to skip) |
| hash | string | "'SHA-256'" | HMAC hash function to use |
* [hkdf(ikm, length, salt, info, hash)](#hkdf) ⇒ Buffer
* [.hash_length(hash)](#hkdf.hash_length) ⇒ integer
* [.extract(hash, hash_len, ikm, salt)](#hkdf.extract) ⇒ Buffer
* [.expand(hash, hash_len, prk, length, info)](#hkdf.expand) ⇒ Buffer
### hkdf.hash\_length(hash) ⇒ integer
Get expected hash length.
**Kind**: static method of [hkdf](#hkdf)
**Returns**: integer - hash digest byte length
**Note**: Values are hardcoded with fallback for unknown algorithms.
| Param | Type | Description |
| --- | --- | --- |
| hash | string | Hash algorithm (as in underlying Node.js crypto library) |
### hkdf.extract(hash, hash_len, ikm, salt) ⇒ Buffer
HKDF extract action.
**Kind**: static method of [hkdf](#hkdf)
**Returns**: Buffer - A buffer with pseudorandom key
**Note**: Values are hardcoded with fallback for unknown algorithms.
| Param | Type | Description |
| --- | --- | --- |
| hash | string | Hash algorithm (as in underlying Node.js crypto library) |
| hash_len | integer | Hash digest length |
| ikm | Buffer \| string | Initial Keying Material |
| salt | Buffer \| string | Optional salt (recommended) |
### hkdf.expand(hash, hash_len, prk, length, info) ⇒ Buffer
HKDF expand action.
**Kind**: static method of [hkdf](#hkdf)
**Returns**: Buffer - A buffer with output keying material
**Note**: Values are hardcoded with fallback for unknown algorithms.
| Param | Type | Description |
| --- | --- | --- |
| hash | string | Hash algorithm (as in underlying Node.js crypto library) |
| hash_len | integer | Hash digest length |
| prk | Buffer \| string | A buffer with pseudorandom key |
| length | integer | length of output keying material in octets |
| info | Buffer \| string | Optional context (safe to skip) |
## tls(ikm, length, salt, label, info, hash) ⇒ Buffer
TLS v1.3 HKDF-extract + HKFD-Expand-Label action
**Kind**: global function
**Returns**: Buffer - Raw buffer with derived key of @p length bytes
**Note**: label and context are limited to 255 bytes!
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| ikm | Buffer \| string | | Initial Keying Material |
| length | integer | | Required byte length of output |
| salt | Buffer \| string | '' | Optional salt (required by fact) |
| label | Buffer \| string | '' | Optional label (required by fact) |
| info | Buffer \| string | '' | Optional context (safe to skip) |
| hash | string | "'SHA-256'" | HMAC hash function to use |
* [tls(ikm, length, salt, label, info, hash)](#tls) ⇒ Buffer
* [.info(length, label, context)](#tls.info) ⇒ Buffer
* [.expand_label(hash, hash_len, prk, length, label, context)](#tls.expand_label) ⇒ Buffer
### tls.info(length, label, context) ⇒ Buffer
Encode HKDF context parameter in TLS v1.3 style based on RFC8446 TLS v1.3.
**Kind**: static method of [tls](#tls)
**Returns**: Buffer - A buffer with encoded HKDF context
**Note**: label and context are limited to 255 bytes!
| Param | Type | Description |
| --- | --- | --- |
| length | integer | length of output keying material in octets |
| label | string | ASCII label |
| context | Buffer \| string | Binary context or empty string |
### tls.expand\_label(hash, hash_len, prk, length, label, context) ⇒ Buffer
TLS-HKDF expand label action - a HKDF-Expand-Label variation based on RFC8446 TLS v1.3.
**Kind**: static method of [tls](#tls)
**Returns**: Buffer - A buffer with output keying material
**Note**: label and context are limited to 255 bytes!
| Param | Type | Description |
| --- | --- | --- |
| hash | string | Hash algorithm (as in underlying Node.js crypto library) |
| hash_len | integer | Hash digest length |
| prk | Buffer \| string | A buffer with pseudorandom key |
| length | integer | length of output keying material in octets |
| label | string | ASCII label |
| context | Buffer \| string | Binary context or empty string |