All files / src/command/dappServer HKDF.js

100% Statements 22/22
100% Branches 4/4
100% Functions 2/2
100% Lines 21/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55                  5x 1x   4x 4x 4x 4x 4x 4x 4x                     3x 3x 3x 3x 3x 3x 3x 3x 3x 3x   3x             7x              
import { createHmac } from 'crypto';
 
class HKDF {
  /**
   * @param {string} hash
   * @param {Buffer} salt
   * @param {string} initialKey
   */
  constructor(hash, salt, initialKey) {
    if (!HKDF.hashList[hash]) {
      throw new Error('not supported hash method');
    }
    this.hashMethod = hash;
    this.hashLength = HKDF.hashList[hash];
    this.salt = salt;
    this.initialKey = initialKey;
    const hmac = createHmac(hash, this.salt);
    hmac.update(this.initialKey);
    this.prk = hmac.digest();
  }
 
  /**
   * Expands the pseudorandom key to the desired length.
   * @param {string} [info] - Optional context and application-specific information.
   * @param {number} [size] - The length of the output keying material in bytes.
   * @returns {Buffer} - The expanded keying material.
   */
  expand(info = '', size = 32) {
    /** @type {string | Buffer} */
    let pre = '';
    const output = [];
    const numBlocks = Math.ceil(size / this.hashLength);
    for (let i = 0; i < numBlocks; i++) {
      const hmac = createHmac(this.hashMethod, this.prk);
      hmac.update(pre);
      hmac.update(info);
      hmac.update(Buffer.alloc(1, i + 1));
      pre = hmac.digest();
      output.push(pre);
    }
    return Buffer.concat(output, size);
  }
}
/**
 * A static property that maps hash algorithm names to their output lengths in bytes.
 * @type {{ [key: string]: number }}
 */
HKDF.hashList = {
  sha256: 32,
  sha224: 54,
  sha512: 64
};
 
export default HKDF;