| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 | 'use strict';var hash = require('hash.js');var utils = require('minimalistic-crypto-utils');var assert = require('minimalistic-assert');function HmacDRBG(options) {  if (!(this instanceof HmacDRBG))    return new HmacDRBG(options);  this.hash = options.hash;  this.predResist = !!options.predResist;  this.outLen = this.hash.outSize;  this.minEntropy = options.minEntropy || this.hash.hmacStrength;  this._reseed = null;  this.reseedInterval = null;  this.K = null;  this.V = null;  var entropy = utils.toArray(options.entropy, options.entropyEnc || 'hex');  var nonce = utils.toArray(options.nonce, options.nonceEnc || 'hex');  var pers = utils.toArray(options.pers, options.persEnc || 'hex');  assert(entropy.length >= (this.minEntropy / 8),         'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');  this._init(entropy, nonce, pers);}module.exports = HmacDRBG;HmacDRBG.prototype._init = function init(entropy, nonce, pers) {  var seed = entropy.concat(nonce).concat(pers);  this.K = new Array(this.outLen / 8);  this.V = new Array(this.outLen / 8);  for (var i = 0; i < this.V.length; i++) {    this.K[i] = 0x00;    this.V[i] = 0x01;  }  this._update(seed);  this._reseed = 1;  this.reseedInterval = 0x1000000000000;  // 2^48};HmacDRBG.prototype._hmac = function hmac() {  return new hash.hmac(this.hash, this.K);};HmacDRBG.prototype._update = function update(seed) {  var kmac = this._hmac()                 .update(this.V)                 .update([ 0x00 ]);  if (seed)    kmac = kmac.update(seed);  this.K = kmac.digest();  this.V = this._hmac().update(this.V).digest();  if (!seed)    return;  this.K = this._hmac()               .update(this.V)               .update([ 0x01 ])               .update(seed)               .digest();  this.V = this._hmac().update(this.V).digest();};HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) {  // Optional entropy enc  if (typeof entropyEnc !== 'string') {    addEnc = add;    add = entropyEnc;    entropyEnc = null;  }  entropy = utils.toArray(entropy, entropyEnc);  add = utils.toArray(add, addEnc);  assert(entropy.length >= (this.minEntropy / 8),         'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');  this._update(entropy.concat(add || []));  this._reseed = 1;};HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) {  if (this._reseed > this.reseedInterval)    throw new Error('Reseed is required');  // Optional encoding  if (typeof enc !== 'string') {    addEnc = add;    add = enc;    enc = null;  }  // Optional additional data  if (add) {    add = utils.toArray(add, addEnc || 'hex');    this._update(add);  }  var temp = [];  while (temp.length < len) {    this.V = this._hmac().update(this.V).digest();    temp = temp.concat(this.V);  }  var res = temp.slice(0, len);  this._update(add);  this._reseed++;  return utils.encode(res, enc);};
 |