sfccxt
Version:
A JavaScript / Python / PHP cryptocurrency trading library with support for 130+ exchanges
115 lines (95 loc) • 3.21 kB
JavaScript
'use strict';
var CryptoJS = require('../../../crypto-js/crypto-js');
var assert = require('../elliptic/utils').assert;
var utils = require ('../elliptic/utils')
var { byteArrayToWordArray } = require('../../../../base/functions/encode');
// some static stuff
const ONE = CryptoJS.enc.Utf8.parse ('\x01')
const ZERO = CryptoJS.enc.Utf8.parse ('\x00')
function HmacDRBG(options) {
if (!(this instanceof HmacDRBG))
return new HmacDRBG(options);
this.hash = options.hash
this.predResist = !!options.predResist;
this.outLen = this.hash.slice (3, 6); // only support SHAXXX hashes
this.minEntropy = options.minEntropy || 192;
this._reseed = null;
this.reseedInterval = null;
this.K = null;
this.V = null;
var entropy = options.entropy
var nonce = options.nonce
var pers = []
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 CryptoJS.lib.WordArray.init ()
this.V = new CryptoJS.lib.WordArray.init ()
const magicNumber = (1 << 24) + (1 << 16) + (1 << 8) + 1
this.V.words = Array (this.outLen / 32).fill (magicNumber)
this.V.sigBytes = 32
this._update(seed);
this._reseed = 1;
this.reseedInterval = 0x1000000000000; // 2^48
};
HmacDRBG.prototype._hmac = function hmac() {
return new CryptoJS.lib.WordArray.init ();
};
HmacDRBG.prototype._update = function update(seed) {
var kmac = this._hmac ()
kmac.concat (this.V)
kmac.concat (ZERO)
if (seed)
kmac.concat (byteArrayToWordArray (seed));
this.K = CryptoJS['Hmac' + this.hash] (kmac, this.K)
this.V = CryptoJS['Hmac' + this.hash] (this.V, this.K)
if (!seed)
return;
kmac = this._hmac ()
kmac.concat (this.V)
kmac.concat (ONE)
kmac.concat (byteArrayToWordArray (seed))
this.K = CryptoJS['Hmac' + this.hash] (kmac, this.K)
this.V = CryptoJS['Hmac' + this.hash] (this.V, this.K)
};
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 = CryptoJS.enc.Utf8.parse (add);
this._update (add);
}
var res = new CryptoJS.lib.WordArray.init ();
while (res.sigBytes < len) {
this.V = CryptoJS['Hmac' + this.hash] (this.V, this.K)
res.concat (this.V);
}
this._update (add);
this._reseed++;
return utils.wordArrayToBuffer(res);
};