Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80575 views
1
'use strict';
2
3
var hash = require('hash.js');
4
var elliptic = require('../elliptic');
5
var utils = elliptic.utils;
6
var assert = utils.assert;
7
8
function HmacDRBG(options) {
9
if (!(this instanceof HmacDRBG))
10
return new HmacDRBG(options);
11
this.hash = options.hash;
12
this.predResist = !!options.predResist;
13
14
this.outLen = this.hash.outSize;
15
this.minEntropy = options.minEntropy || this.hash.hmacStrength;
16
17
this.reseed = null;
18
this.reseedInterval = null;
19
this.K = null;
20
this.V = null;
21
22
var entropy = utils.toArray(options.entropy, options.entropyEnc);
23
var nonce = utils.toArray(options.nonce, options.nonceEnc);
24
var pers = utils.toArray(options.pers, options.persEnc);
25
assert(entropy.length >= (this.minEntropy / 8),
26
'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');
27
this._init(entropy, nonce, pers);
28
}
29
module.exports = HmacDRBG;
30
31
HmacDRBG.prototype._init = function init(entropy, nonce, pers) {
32
var seed = entropy.concat(nonce).concat(pers);
33
34
this.K = new Array(this.outLen / 8);
35
this.V = new Array(this.outLen / 8);
36
for (var i = 0; i < this.V.length; i++) {
37
this.K[i] = 0x00;
38
this.V[i] = 0x01;
39
}
40
41
this._update(seed);
42
this.reseed = 1;
43
this.reseedInterval = 0x1000000000000; // 2^48
44
};
45
46
HmacDRBG.prototype._hmac = function hmac() {
47
return new hash.hmac(this.hash, this.K);
48
};
49
50
HmacDRBG.prototype._update = function update(seed) {
51
var kmac = this._hmac()
52
.update(this.V)
53
.update([ 0x00 ]);
54
if (seed)
55
kmac = kmac.update(seed);
56
this.K = kmac.digest();
57
this.V = this._hmac().update(this.V).digest();
58
if (!seed)
59
return;
60
61
this.K = this._hmac()
62
.update(this.V)
63
.update([ 0x01 ])
64
.update(seed)
65
.digest();
66
this.V = this._hmac().update(this.V).digest();
67
};
68
69
HmacDRBG.prototype.reseed = function reseed(entropy, entropyEnc, add, addEnc) {
70
// Optional entropy enc
71
if (typeof entropyEnc !== 'string') {
72
addEnc = add;
73
add = entropyEnc;
74
entropyEnc = null;
75
}
76
77
entropy = utils.toBuffer(entropy, entropyEnc);
78
add = utils.toBuffer(add, addEnc);
79
80
assert(entropy.length >= (this.minEntropy / 8),
81
'Not enough entropy. Minimum is: ' + this.minEntropy + ' bits');
82
83
this._update(entropy.concat(add || []));
84
this.reseed = 1;
85
};
86
87
HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) {
88
if (this.reseed > this.reseedInterval)
89
throw new Error('Reseed is required');
90
91
// Optional encoding
92
if (typeof enc !== 'string') {
93
addEnc = add;
94
add = enc;
95
enc = null;
96
}
97
98
// Optional additional data
99
if (add) {
100
add = utils.toArray(add, addEnc);
101
this._update(add);
102
}
103
104
var temp = [];
105
while (temp.length < len) {
106
this.V = this._hmac().update(this.V).digest();
107
temp = temp.concat(this.V);
108
}
109
110
var res = temp.slice(0, len);
111
this._update(add);
112
this.reseed++;
113
return utils.encode(res, enc);
114
};
115
116