You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
'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); };
|