[![NPM Version](https://img.shields.io/npm/v/futoin-hkdf.svg?style=flat)](https://www.npmjs.com/package/futoin-hkdf) [![NPM Downloads](https://img.shields.io/npm/dm/futoin-hkdf.svg?style=flat)](https://www.npmjs.com/package/futoin-hkdf) [![Build Status](https://travis-ci.org/futoin/util-js-hkdf.svg)](https://travis-ci.org/futoin/util-js-hkdf) [![stable](https://img.shields.io/badge/stability-stable-green.svg?style=flat)](https://www.npmjs.com/package/futoin-hkdf) [![NPM](https://nodei.co/npm/futoin-hkdf.png?downloads=true&downloadRank=true&stars=true)](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). 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 ``` # API documentation ## hkdf(ikm, length, salt, info, hash) ⇒ 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) |