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;
|