Skip to content

Commit 9e3ae69

Browse files
committed
Params object for Entropy constructor
1 parent 91e3f0b commit 9e3ae69

File tree

3 files changed

+212
-136
lines changed

3 files changed

+212
-136
lines changed

dist/lib/entropy.js

Lines changed: 78 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,23 @@ var _stringWithBytes = function _stringWithBytes(bytes, bitLen, charset) {
4848
return '';
4949
}
5050

51+
var floor = Math.floor,
52+
ceil = Math.ceil;
53+
54+
5155
var bitsPerChar = charset.getBitsPerChar();
52-
var count = Math.ceil(bitLen / bitsPerChar);
56+
var count = ceil(bitLen / bitsPerChar);
5357
if (count <= 0) {
5458
return '';
5559
}
5660

57-
var need = Math.ceil(count * (bitsPerChar / BITS_PER_BYTE));
61+
var need = ceil(count * (bitsPerChar / BITS_PER_BYTE));
5862
if (bytes.length < need) {
5963
throw new Error('Insufficient bytes: need ' + need + ' and got ' + bytes.length);
6064
}
6165

6266
var charsPerChunk = charset.getCharsPerChunk();
63-
var chunks = Math.floor(count / charsPerChunk);
67+
var chunks = floor(count / charsPerChunk);
6468
var partials = count % charsPerChunk;
6569

6670
var ndxFn = charset.getNdxFn();
@@ -118,51 +122,85 @@ var entropyBits = function entropyBits(total, risk) {
118122
return N + log2(risk) - 1;
119123
};
120124

121-
var createCharset = function createCharset(arg) {
122-
if (arg instanceof CharSet) {
123-
return arg;
124-
} else if (typeof arg === 'string' || arg instanceof String) {
125-
return new CharSet(arg);
126-
}
127-
return charset32;
128-
};
129-
130125
var _class = function () {
131126
function _class() {
132-
var arg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { bits: 128, charset: charset32 };
127+
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { bits: 128, charset: charset32 };
133128
(0, _classCallCheck3.default)(this, _class);
134129

135-
var charset = void 0;
136-
var bitLen = 0;
137-
138-
if (arg instanceof CharSet || arg instanceof String || typeof arg === 'string') {
139-
charset = createCharset(arg);
140-
} else if (arg instanceof Object) {
141-
var round = Math.round;
142-
143-
if (typeof arg.bits === 'number') {
144-
bitLen = round(arg.bits);
145-
} else if (typeof arg.total === 'number' && typeof arg.risk === 'number') {
146-
bitLen = round(entropyBits(arg.total, arg.risk));
147-
} else {
148-
bitLen = 128;
130+
if (params !== undefined) {
131+
if (!(params instanceof Object)) {
132+
throw new Error('Invalid argument for Entropy constructor: Expect params object');
133+
}
134+
135+
if (params.bits === undefined && params.charset === undefined && params.total === undefined && params.risk === undefined) {
136+
throw new Error('Invalid Entropy params');
137+
}
138+
139+
if (params.bits !== undefined) {
140+
if (typeof params.bits !== 'number') {
141+
throw new Error('Invalid Entropy params: non-numeric bits');
142+
}
143+
if (params.bits < 0) {
144+
throw new Error('Invalid Entropy params: negative bits');
145+
}
146+
}
147+
148+
if (params.total !== undefined) {
149+
if (typeof params.total !== 'number') {
150+
throw new Error('Invalid Entropy params: non-numeric total');
151+
}
152+
if (params.total < 1) {
153+
throw new Error('Invalid Entropy params: non-positive total');
154+
}
155+
}
156+
157+
if (params.risk !== undefined) {
158+
if (typeof params.risk !== 'number') {
159+
throw new Error('Invalid Entropy params: non-numeric risk');
160+
}
161+
if (params.risk < 1) {
162+
throw new Error('Invalid Entropy params: non-positive risk');
163+
}
164+
}
165+
166+
if (params.risk !== undefined && typeof params.risk !== 'number') {
167+
throw new Error('Invalid Entropy params: non-numeric risk');
168+
}
169+
170+
if (params.total !== undefined && params.risk === undefined || params.total === undefined && params.risk !== undefined) {
171+
throw new Error('Invalid Entropy params: total and risk must be paired');
172+
}
173+
174+
if (params.bits !== undefined && (params.total !== undefined || params.risk !== undefined)) {
175+
throw new Error('Invalid Entropy params: bits with total and/or risk');
149176
}
150-
charset = createCharset(arg.charset);
177+
}
178+
179+
var bitLen = void 0;
180+
var round = Math.round;
181+
182+
if (params.bits) {
183+
bitLen = round(params.bits);
184+
} else if (params.total && params.risk) {
185+
bitLen = round(entropyBits(params.total, params.risk));
151186
} else {
152-
throw new Error('Constructor arg must either be a valid CharSet, valid characters, or valid Entropy params');
187+
bitLen = 128;
153188
}
154189

155-
if (charset === undefined) {
156-
throw new Error('Invalid constructor CharSet declaration');
157-
} else if (bitLen < 0) {
158-
throw new Error('Invalid constructor declaration of bits less than zero');
190+
var charset = void 0;
191+
if (params.charset instanceof CharSet) {
192+
var cs = params.charset;
193+
194+
charset = cs;
195+
} else if (typeof params.charset === 'string' || params.charset instanceof String) {
196+
charset = new CharSet(params.charset);
197+
} else {
198+
charset = charset32;
159199
}
160200

161-
propMap.set(this, {
162-
charset: charset,
163-
bitLen: bitLen,
164-
bytesNeeded: charset.bytesNeeded(bitLen)
165-
});
201+
var prng = params.prng || false;
202+
203+
propMap.set(this, { charset: charset, bitLen: bitLen, prng: prng });
166204
}
167205

168206
(0, _createClass3.default)(_class, [{
@@ -218,22 +256,10 @@ var _class = function () {
218256
var bytesNeeded = charset.bytesNeeded(bitLen);
219257
return this.stringWithBytes(randomBytes(bytesNeeded), bitLen, charset);
220258
}
221-
222-
/**
223-
* @deprecated Since version 3.1. Will be deleted in version 4.0. Use stringPRNG instead.
224-
*/
225-
226-
}, {
227-
key: 'stringRandom',
228-
value: function stringRandom() {
229-
var bitLen = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : propMap.get(this).bitLen;
230-
var charset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : propMap.get(this).charset;
231-
232-
return this.stringPRNG(bitLen, charset);
233-
}
234259
}, {
235260
key: 'stringWithBytes',
236-
value: function stringWithBytes(bytes, bitLen) {
261+
value: function stringWithBytes(bytes) {
262+
var bitLen = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : propMap.get(this).bitLen;
237263
var charset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : propMap.get(this).charset;
238264

239265
return _stringWithBytes(bytes, bitLen, charset);

lib/entropy.js

Lines changed: 75 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,19 @@ const endianByteNum = (() => {
2424
const stringWithBytes = (bytes, bitLen, charset) => {
2525
if (bitLen <= 0) { return '' }
2626

27+
const { floor, ceil } = Math
28+
2729
const bitsPerChar = charset.getBitsPerChar()
28-
const count = Math.ceil(bitLen / bitsPerChar)
30+
const count = ceil(bitLen / bitsPerChar)
2931
if (count <= 0) { return '' }
3032

31-
const need = Math.ceil(count * (bitsPerChar / BITS_PER_BYTE))
33+
const need = ceil(count * (bitsPerChar / BITS_PER_BYTE))
3234
if (bytes.length < need) {
3335
throw new Error(`Insufficient bytes: need ${need} and got ${bytes.length}`)
3436
}
3537

3638
const charsPerChunk = charset.getCharsPerChunk()
37-
const chunks = Math.floor(count / charsPerChunk)
39+
const chunks = floor(count / charsPerChunk)
3840
const partials = count % charsPerChunk
3941

4042
const ndxFn = charset.getNdxFn()
@@ -87,47 +89,83 @@ const entropyBits = (total, risk) => {
8789
return (N + log2(risk)) - 1
8890
}
8991

90-
const createCharset = (arg) => {
91-
if (arg instanceof CharSet) {
92-
return arg
93-
} else if ((typeof arg === 'string' || arg instanceof String)) {
94-
return new CharSet(arg)
95-
}
96-
return charset32
97-
}
98-
9992
export default class {
100-
constructor(arg = { bits: 128, charset: charset32 }) {
101-
let charset
102-
let bitLen = 0
103-
104-
if (arg instanceof CharSet || arg instanceof String || typeof arg === 'string') {
105-
charset = createCharset(arg)
106-
} else if (arg instanceof Object) {
107-
const { round } = Math
108-
if (typeof arg.bits === 'number') {
109-
bitLen = round(arg.bits)
110-
} else if (typeof arg.total === 'number' && typeof arg.risk === 'number') {
111-
bitLen = round(entropyBits(arg.total, arg.risk))
112-
} else {
113-
bitLen = 128
93+
constructor(params = { bits: 128, charset: charset32 }) {
94+
if (params !== undefined) {
95+
if (!(params instanceof Object)) {
96+
throw new Error('Invalid argument for Entropy constructor: Expect params object')
97+
}
98+
99+
if (params.bits === undefined &&
100+
params.charset === undefined &&
101+
params.total === undefined &&
102+
params.risk === undefined) {
103+
throw new Error('Invalid Entropy params')
104+
}
105+
106+
if (params.bits !== undefined) {
107+
if (typeof params.bits !== 'number') {
108+
throw new Error('Invalid Entropy params: non-numeric bits')
109+
}
110+
if (params.bits < 0) {
111+
throw new Error('Invalid Entropy params: negative bits')
112+
}
114113
}
115-
charset = createCharset(arg.charset)
114+
115+
if (params.total !== undefined) {
116+
if (typeof params.total !== 'number') {
117+
throw new Error('Invalid Entropy params: non-numeric total')
118+
}
119+
if (params.total < 1) {
120+
throw new Error('Invalid Entropy params: non-positive total')
121+
}
122+
}
123+
124+
if (params.risk !== undefined) {
125+
if (typeof params.risk !== 'number') {
126+
throw new Error('Invalid Entropy params: non-numeric risk')
127+
}
128+
if (params.risk < 1) {
129+
throw new Error('Invalid Entropy params: non-positive risk')
130+
}
131+
}
132+
133+
if (params.risk !== undefined && typeof params.risk !== 'number') {
134+
throw new Error('Invalid Entropy params: non-numeric risk')
135+
}
136+
137+
if ((params.total !== undefined && params.risk === undefined) ||
138+
(params.total === undefined && params.risk !== undefined)) {
139+
throw new Error('Invalid Entropy params: total and risk must be paired')
140+
}
141+
142+
if (params.bits !== undefined &&
143+
(params.total !== undefined || params.risk !== undefined)) {
144+
throw new Error('Invalid Entropy params: bits with total and/or risk')
145+
}
146+
}
147+
148+
let bitLen
149+
const { round } = Math
150+
if (params.bits) {
151+
bitLen = round(params.bits)
152+
} else if (params.total && params.risk) {
153+
bitLen = round(entropyBits(params.total, params.risk))
116154
} else {
117-
throw new Error('Constructor arg must either be a valid CharSet, valid characters, or valid Entropy params')
155+
bitLen = 128
118156
}
119157

120-
if (charset === undefined) {
121-
throw new Error('Invalid constructor CharSet declaration')
122-
} else if (bitLen < 0) {
123-
throw new Error('Invalid constructor declaration of bits less than zero')
158+
let charset
159+
if (params.charset instanceof CharSet) {
160+
const { charset: cs } = params
161+
charset = cs
162+
} else if ((typeof params.charset === 'string' || params.charset instanceof String)) {
163+
charset = new CharSet(params.charset)
164+
} else {
165+
charset = charset32
124166
}
125167

126-
propMap.set(this, {
127-
charset,
128-
bitLen,
129-
bytesNeeded: charset.bytesNeeded(bitLen)
130-
})
168+
propMap.set(this, { charset, bitLen })
131169
}
132170

133171
static bits(total, risk) { return entropyBits(total, risk) }

0 commit comments

Comments
 (0)