@ray-js/wechat-rsa 0.0.1-beta-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index..js +3709 -0
- package/index.esm.js +3704 -0
- package/package.json +19 -0
- package/src/JSEncrypt.d.ts +54 -0
- package/src/JSEncryptRSAKey.d.ts +59 -0
- package/src/index.d.ts +3 -0
- package/src/lib/asn1js/asn1.d.ts +51 -0
- package/src/lib/asn1js/base64.d.ts +5 -0
- package/src/lib/asn1js/hex.d.ts +3 -0
- package/src/lib/asn1js/int10.d.ts +9 -0
- package/src/lib/asn1js/oids.d.ts +9778 -0
- package/src/lib/jsbn/base64.d.ts +3 -0
- package/src/lib/jsbn/jsbn.d.ts +98 -0
- package/src/lib/jsbn/prng4.d.ts +10 -0
- package/src/lib/jsbn/rng.d.ts +3 -0
- package/src/lib/jsbn/rsa.d.ts +16 -0
- package/src/lib/jsbn/util.d.ts +7 -0
package/index..js
ADDED
|
@@ -0,0 +1,3709 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
const BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
6
|
+
function int2char(n) {
|
|
7
|
+
return BI_RM.charAt(n);
|
|
8
|
+
} //#region BIT_OPERATIONS
|
|
9
|
+
// (public) this & a
|
|
10
|
+
|
|
11
|
+
function op_and(x, y) {
|
|
12
|
+
return x & y;
|
|
13
|
+
} // (public) this | a
|
|
14
|
+
|
|
15
|
+
function op_or(x, y) {
|
|
16
|
+
return x | y;
|
|
17
|
+
} // (public) this ^ a
|
|
18
|
+
|
|
19
|
+
function op_xor(x, y) {
|
|
20
|
+
return x ^ y;
|
|
21
|
+
} // (public) this & ~a
|
|
22
|
+
|
|
23
|
+
function op_andnot(x, y) {
|
|
24
|
+
return x & ~y;
|
|
25
|
+
} // return index of lowest 1-bit in x, x < 2^31
|
|
26
|
+
|
|
27
|
+
function lbit(x) {
|
|
28
|
+
if (x == 0) {
|
|
29
|
+
return -1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let r = 0;
|
|
33
|
+
|
|
34
|
+
if ((x & 0xffff) == 0) {
|
|
35
|
+
x >>= 16;
|
|
36
|
+
r += 16;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if ((x & 0xff) == 0) {
|
|
40
|
+
x >>= 8;
|
|
41
|
+
r += 8;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if ((x & 0xf) == 0) {
|
|
45
|
+
x >>= 4;
|
|
46
|
+
r += 4;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if ((x & 3) == 0) {
|
|
50
|
+
x >>= 2;
|
|
51
|
+
r += 2;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if ((x & 1) == 0) {
|
|
55
|
+
++r;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return r;
|
|
59
|
+
} // return number of 1 bits in x
|
|
60
|
+
|
|
61
|
+
function cbit(x) {
|
|
62
|
+
let r = 0;
|
|
63
|
+
|
|
64
|
+
while (x != 0) {
|
|
65
|
+
x &= x - 1;
|
|
66
|
+
++r;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return r;
|
|
70
|
+
} //#endregion BIT_OPERATIONS
|
|
71
|
+
|
|
72
|
+
const b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
73
|
+
const b64pad = "=";
|
|
74
|
+
function hex2b64(h) {
|
|
75
|
+
let i;
|
|
76
|
+
let c;
|
|
77
|
+
let ret = "";
|
|
78
|
+
|
|
79
|
+
for (i = 0; i + 3 <= h.length; i += 3) {
|
|
80
|
+
c = parseInt(h.substring(i, i + 3), 16);
|
|
81
|
+
ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (i + 1 == h.length) {
|
|
85
|
+
c = parseInt(h.substring(i, i + 1), 16);
|
|
86
|
+
ret += b64map.charAt(c << 2);
|
|
87
|
+
} else if (i + 2 == h.length) {
|
|
88
|
+
c = parseInt(h.substring(i, i + 2), 16);
|
|
89
|
+
ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
while ((ret.length & 3) > 0) {
|
|
93
|
+
ret += b64pad;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return ret;
|
|
97
|
+
} // convert a base64 string to hex
|
|
98
|
+
|
|
99
|
+
// Hex JavaScript decoder
|
|
100
|
+
// Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
|
|
101
|
+
// Permission to use, copy, modify, and/or distribute this software for any
|
|
102
|
+
// purpose with or without fee is hereby granted, provided that the above
|
|
103
|
+
// copyright notice and this permission notice appear in all copies.
|
|
104
|
+
//
|
|
105
|
+
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
106
|
+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
107
|
+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
108
|
+
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
109
|
+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
110
|
+
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
111
|
+
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
112
|
+
|
|
113
|
+
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
|
114
|
+
let decoder$1;
|
|
115
|
+
const Hex = {
|
|
116
|
+
decode(a) {
|
|
117
|
+
let i;
|
|
118
|
+
|
|
119
|
+
if (decoder$1 === undefined) {
|
|
120
|
+
let hex = "0123456789ABCDEF";
|
|
121
|
+
const ignore = " \f\n\r\t\u00A0\u2028\u2029";
|
|
122
|
+
decoder$1 = {};
|
|
123
|
+
|
|
124
|
+
for (i = 0; i < 16; ++i) {
|
|
125
|
+
decoder$1[hex.charAt(i)] = i;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
hex = hex.toLowerCase();
|
|
129
|
+
|
|
130
|
+
for (i = 10; i < 16; ++i) {
|
|
131
|
+
decoder$1[hex.charAt(i)] = i;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
for (i = 0; i < ignore.length; ++i) {
|
|
135
|
+
decoder$1[ignore.charAt(i)] = -1;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const out = [];
|
|
140
|
+
let bits = 0;
|
|
141
|
+
let char_count = 0;
|
|
142
|
+
|
|
143
|
+
for (i = 0; i < a.length; ++i) {
|
|
144
|
+
let c = a.charAt(i);
|
|
145
|
+
|
|
146
|
+
if (c == "=") {
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
c = decoder$1[c];
|
|
151
|
+
|
|
152
|
+
if (c == -1) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (c === undefined) {
|
|
157
|
+
throw new Error("Illegal character at offset " + i);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
bits |= c;
|
|
161
|
+
|
|
162
|
+
if (++char_count >= 2) {
|
|
163
|
+
out[out.length] = bits;
|
|
164
|
+
bits = 0;
|
|
165
|
+
char_count = 0;
|
|
166
|
+
} else {
|
|
167
|
+
bits <<= 4;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (char_count) {
|
|
172
|
+
throw new Error("Hex encoding incomplete: 4 bits missing");
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// Base64 JavaScript decoder
|
|
181
|
+
// Copyright (c) 2008-2013 Lapo Luchini <lapo@lapo.it>
|
|
182
|
+
// Permission to use, copy, modify, and/or distribute this software for any
|
|
183
|
+
// purpose with or without fee is hereby granted, provided that the above
|
|
184
|
+
// copyright notice and this permission notice appear in all copies.
|
|
185
|
+
//
|
|
186
|
+
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
187
|
+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
188
|
+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
189
|
+
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
190
|
+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
191
|
+
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
192
|
+
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
193
|
+
|
|
194
|
+
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
|
195
|
+
let decoder;
|
|
196
|
+
const Base64 = {
|
|
197
|
+
decode(a) {
|
|
198
|
+
let i;
|
|
199
|
+
|
|
200
|
+
if (decoder === undefined) {
|
|
201
|
+
const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
202
|
+
const ignore = "= \f\n\r\t\u00A0\u2028\u2029";
|
|
203
|
+
decoder = Object.create(null);
|
|
204
|
+
|
|
205
|
+
for (i = 0; i < 64; ++i) {
|
|
206
|
+
decoder[b64.charAt(i)] = i;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
decoder['-'] = 62; //+
|
|
210
|
+
|
|
211
|
+
decoder['_'] = 63; //-
|
|
212
|
+
|
|
213
|
+
for (i = 0; i < ignore.length; ++i) {
|
|
214
|
+
decoder[ignore.charAt(i)] = -1;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const out = [];
|
|
219
|
+
let bits = 0;
|
|
220
|
+
let char_count = 0;
|
|
221
|
+
|
|
222
|
+
for (i = 0; i < a.length; ++i) {
|
|
223
|
+
let c = a.charAt(i);
|
|
224
|
+
|
|
225
|
+
if (c == "=") {
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
c = decoder[c];
|
|
230
|
+
|
|
231
|
+
if (c == -1) {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (c === undefined) {
|
|
236
|
+
throw new Error("Illegal character at offset " + i);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
bits |= c;
|
|
240
|
+
|
|
241
|
+
if (++char_count >= 4) {
|
|
242
|
+
out[out.length] = bits >> 16;
|
|
243
|
+
out[out.length] = bits >> 8 & 0xFF;
|
|
244
|
+
out[out.length] = bits & 0xFF;
|
|
245
|
+
bits = 0;
|
|
246
|
+
char_count = 0;
|
|
247
|
+
} else {
|
|
248
|
+
bits <<= 6;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
switch (char_count) {
|
|
253
|
+
case 1:
|
|
254
|
+
throw new Error("Base64 encoding incomplete: at least 2 bits missing");
|
|
255
|
+
|
|
256
|
+
case 2:
|
|
257
|
+
out[out.length] = bits >> 10;
|
|
258
|
+
break;
|
|
259
|
+
|
|
260
|
+
case 3:
|
|
261
|
+
out[out.length] = bits >> 16;
|
|
262
|
+
out[out.length] = bits >> 8 & 0xFF;
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return out;
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
// eslint-disable-next-line no-useless-escape
|
|
270
|
+
re: /-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/,
|
|
271
|
+
|
|
272
|
+
unarmor(a) {
|
|
273
|
+
const m = Base64.re.exec(a);
|
|
274
|
+
|
|
275
|
+
if (m) {
|
|
276
|
+
if (m[1]) {
|
|
277
|
+
a = m[1];
|
|
278
|
+
} else if (m[2]) {
|
|
279
|
+
a = m[2];
|
|
280
|
+
} else {
|
|
281
|
+
throw new Error("RegExp out of sync");
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return Base64.decode(a);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// Big integer base-10 printing library
|
|
291
|
+
// Copyright (c) 2014 Lapo Luchini <lapo@lapo.it>
|
|
292
|
+
// Permission to use, copy, modify, and/or distribute this software for any
|
|
293
|
+
// purpose with or without fee is hereby granted, provided that the above
|
|
294
|
+
// copyright notice and this permission notice appear in all copies.
|
|
295
|
+
//
|
|
296
|
+
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
297
|
+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
298
|
+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
299
|
+
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
300
|
+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
301
|
+
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
302
|
+
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
303
|
+
|
|
304
|
+
/*jshint browser: true, strict: true, immed: true, latedef: true, undef: true, regexdash: false */
|
|
305
|
+
const max = 10000000000000; // biggest integer that can still fit 2^53 when multiplied by 256
|
|
306
|
+
|
|
307
|
+
class Int10 {
|
|
308
|
+
constructor(value) {
|
|
309
|
+
this.buf = [value ? +value : 0];
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
mulAdd(m, c) {
|
|
313
|
+
// assert(m <= 256)
|
|
314
|
+
const b = this.buf;
|
|
315
|
+
const l = b.length;
|
|
316
|
+
let i;
|
|
317
|
+
let t;
|
|
318
|
+
|
|
319
|
+
for (i = 0; i < l; ++i) {
|
|
320
|
+
t = b[i] * m + c;
|
|
321
|
+
|
|
322
|
+
if (t < max) {
|
|
323
|
+
c = 0;
|
|
324
|
+
} else {
|
|
325
|
+
c = 0 | t / max;
|
|
326
|
+
t -= c * max;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
b[i] = t;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (c > 0) {
|
|
333
|
+
b[i] = c;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
sub(c) {
|
|
338
|
+
// assert(m <= 256)
|
|
339
|
+
const b = this.buf;
|
|
340
|
+
const l = b.length;
|
|
341
|
+
let i;
|
|
342
|
+
let t;
|
|
343
|
+
|
|
344
|
+
for (i = 0; i < l; ++i) {
|
|
345
|
+
t = b[i] - c;
|
|
346
|
+
|
|
347
|
+
if (t < 0) {
|
|
348
|
+
t += max;
|
|
349
|
+
c = 1;
|
|
350
|
+
} else {
|
|
351
|
+
c = 0;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
b[i] = t;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
while (b[b.length - 1] === 0) {
|
|
358
|
+
b.pop();
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
toString(base) {
|
|
363
|
+
if ((base || 10) != 10) {
|
|
364
|
+
throw new Error('only base 10 is supported');
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const b = this.buf;
|
|
368
|
+
let s = b[b.length - 1].toString();
|
|
369
|
+
|
|
370
|
+
for (let i = b.length - 2; i >= 0; --i) {
|
|
371
|
+
s += (max + b[i]).toString().substring(1);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return s;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
valueOf() {
|
|
378
|
+
const b = this.buf;
|
|
379
|
+
let v = 0;
|
|
380
|
+
|
|
381
|
+
for (let i = b.length - 1; i >= 0; --i) {
|
|
382
|
+
v = v * max + b[i];
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return v;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
simplify() {
|
|
389
|
+
const b = this.buf;
|
|
390
|
+
return b.length == 1 ? b[0] : this;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// ASN.1 JavaScript decoder
|
|
396
|
+
const ellipsis = '\u2026';
|
|
397
|
+
const reTimeS = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;
|
|
398
|
+
const reTimeL = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;
|
|
399
|
+
|
|
400
|
+
function stringCut(str, len) {
|
|
401
|
+
if (str.length > len) {
|
|
402
|
+
str = str.substring(0, len) + ellipsis;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return str;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
class Stream {
|
|
409
|
+
constructor(enc, pos) {
|
|
410
|
+
this.hexDigits = '0123456789ABCDEF';
|
|
411
|
+
|
|
412
|
+
if (enc instanceof Stream) {
|
|
413
|
+
this.enc = enc.enc;
|
|
414
|
+
this.pos = enc.pos;
|
|
415
|
+
} else {
|
|
416
|
+
// enc should be an array or a binary string
|
|
417
|
+
this.enc = enc;
|
|
418
|
+
this.pos = pos || 0;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
get(pos) {
|
|
423
|
+
if (pos === undefined) {
|
|
424
|
+
pos = this.pos++;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (pos >= this.enc.length) {
|
|
428
|
+
throw new Error(`Requesting byte offset ${pos} on a stream of length ${this.enc.length}`);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return 'string' === typeof this.enc ? this.enc.charCodeAt(pos) : this.enc[pos];
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
hexByte(b) {
|
|
435
|
+
return this.hexDigits.charAt(b >> 4 & 0xf) + this.hexDigits.charAt(b & 0xf);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
hexDump(start, end, raw) {
|
|
439
|
+
let s = '';
|
|
440
|
+
|
|
441
|
+
for (let i = start; i < end; ++i) {
|
|
442
|
+
s += this.hexByte(this.get(i));
|
|
443
|
+
|
|
444
|
+
if (raw !== true) {
|
|
445
|
+
switch (i & 0xf) {
|
|
446
|
+
case 0x7:
|
|
447
|
+
s += ' ';
|
|
448
|
+
break;
|
|
449
|
+
|
|
450
|
+
case 0xf:
|
|
451
|
+
s += '\n';
|
|
452
|
+
break;
|
|
453
|
+
|
|
454
|
+
default:
|
|
455
|
+
s += ' ';
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return s;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
isASCII(start, end) {
|
|
464
|
+
for (let i = start; i < end; ++i) {
|
|
465
|
+
const c = this.get(i);
|
|
466
|
+
|
|
467
|
+
if (c < 32 || c > 176) {
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
return true;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
parseStringISO(start, end) {
|
|
476
|
+
let s = '';
|
|
477
|
+
|
|
478
|
+
for (let i = start; i < end; ++i) {
|
|
479
|
+
s += String.fromCharCode(this.get(i));
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
return s;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
parseStringUTF(start, end) {
|
|
486
|
+
let s = '';
|
|
487
|
+
|
|
488
|
+
for (let i = start; i < end;) {
|
|
489
|
+
const c = this.get(i++);
|
|
490
|
+
|
|
491
|
+
if (c < 128) {
|
|
492
|
+
s += String.fromCharCode(c);
|
|
493
|
+
} else if (c > 191 && c < 224) {
|
|
494
|
+
s += String.fromCharCode((c & 0x1f) << 6 | this.get(i++) & 0x3f);
|
|
495
|
+
} else {
|
|
496
|
+
s += String.fromCharCode((c & 0x0f) << 12 | (this.get(i++) & 0x3f) << 6 | this.get(i++) & 0x3f);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return s;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
parseStringBMP(start, end) {
|
|
504
|
+
let str = '';
|
|
505
|
+
let hi;
|
|
506
|
+
let lo;
|
|
507
|
+
|
|
508
|
+
for (let i = start; i < end;) {
|
|
509
|
+
hi = this.get(i++);
|
|
510
|
+
lo = this.get(i++);
|
|
511
|
+
str += String.fromCharCode(hi << 8 | lo);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
return str;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
parseTime(start, end, shortYear) {
|
|
518
|
+
let s = this.parseStringISO(start, end);
|
|
519
|
+
const m = (shortYear ? reTimeS : reTimeL).exec(s);
|
|
520
|
+
|
|
521
|
+
if (!m) {
|
|
522
|
+
return 'Unrecognized time: ' + s;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (shortYear) {
|
|
526
|
+
// to avoid querying the timer, use the fixed range [1970, 2069]
|
|
527
|
+
// it will conform with ITU X.400 [-10, +40] sliding window until 2030
|
|
528
|
+
m[1] = +m[1];
|
|
529
|
+
m[1] += +m[1] < 70 ? 2000 : 1900;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
s = m[1] + '-' + m[2] + '-' + m[3] + ' ' + m[4];
|
|
533
|
+
|
|
534
|
+
if (m[5]) {
|
|
535
|
+
s += ':' + m[5];
|
|
536
|
+
|
|
537
|
+
if (m[6]) {
|
|
538
|
+
s += ':' + m[6];
|
|
539
|
+
|
|
540
|
+
if (m[7]) {
|
|
541
|
+
s += '.' + m[7];
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if (m[8]) {
|
|
547
|
+
s += ' UTC';
|
|
548
|
+
|
|
549
|
+
if (m[8] != 'Z') {
|
|
550
|
+
s += m[8];
|
|
551
|
+
|
|
552
|
+
if (m[9]) {
|
|
553
|
+
s += ':' + m[9];
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
return s;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
parseInteger(start, end) {
|
|
562
|
+
let v = this.get(start);
|
|
563
|
+
const neg = v > 127;
|
|
564
|
+
const pad = neg ? 255 : 0;
|
|
565
|
+
let len;
|
|
566
|
+
let s = ''; // skip unuseful bits (not allowed in DER)
|
|
567
|
+
|
|
568
|
+
while (v == pad && ++start < end) {
|
|
569
|
+
v = this.get(start);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
len = end - start;
|
|
573
|
+
|
|
574
|
+
if (len === 0) {
|
|
575
|
+
return neg ? -1 : 0;
|
|
576
|
+
} // show bit length of huge integers
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
if (len > 4) {
|
|
580
|
+
s = v;
|
|
581
|
+
len <<= 3;
|
|
582
|
+
|
|
583
|
+
while (((+s ^ pad) & 0x80) == 0) {
|
|
584
|
+
s = +s << 1;
|
|
585
|
+
--len;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
s = '(' + len + ' bit)\n';
|
|
589
|
+
} // decode the integer
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
if (neg) {
|
|
593
|
+
v = v - 256;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
const n = new Int10(v);
|
|
597
|
+
|
|
598
|
+
for (let i = start + 1; i < end; ++i) {
|
|
599
|
+
n.mulAdd(256, this.get(i));
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return s + n.toString();
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
parseBitString(start, end, maxLength) {
|
|
606
|
+
const unusedBit = this.get(start);
|
|
607
|
+
const lenBit = (end - start - 1 << 3) - unusedBit;
|
|
608
|
+
const intro = '(' + lenBit + ' bit)\n';
|
|
609
|
+
let s = '';
|
|
610
|
+
|
|
611
|
+
for (let i = start + 1; i < end; ++i) {
|
|
612
|
+
const b = this.get(i);
|
|
613
|
+
const skip = i == end - 1 ? unusedBit : 0;
|
|
614
|
+
|
|
615
|
+
for (let j = 7; j >= skip; --j) {
|
|
616
|
+
s += b >> j & 1 ? '1' : '0';
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
if (s.length > maxLength) {
|
|
620
|
+
return intro + stringCut(s, maxLength);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
return intro + s;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
parseOctetString(start, end, maxLength) {
|
|
628
|
+
if (this.isASCII(start, end)) {
|
|
629
|
+
return stringCut(this.parseStringISO(start, end), maxLength);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
const len = end - start;
|
|
633
|
+
let s = '(' + len + ' byte)\n';
|
|
634
|
+
maxLength /= 2; // we work in bytes
|
|
635
|
+
|
|
636
|
+
if (len > maxLength) {
|
|
637
|
+
end = start + maxLength;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
for (let i = start; i < end; ++i) {
|
|
641
|
+
s += this.hexByte(this.get(i));
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (len > maxLength) {
|
|
645
|
+
s += ellipsis;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
return s;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
parseOID(start, end, maxLength) {
|
|
652
|
+
let s = '';
|
|
653
|
+
let n = new Int10();
|
|
654
|
+
let bits = 0;
|
|
655
|
+
|
|
656
|
+
for (let i = start; i < end; ++i) {
|
|
657
|
+
const v = this.get(i);
|
|
658
|
+
n.mulAdd(128, v & 0x7f);
|
|
659
|
+
bits += 7;
|
|
660
|
+
|
|
661
|
+
if (!(v & 0x80)) {
|
|
662
|
+
// finished
|
|
663
|
+
if (s === '') {
|
|
664
|
+
n = n.simplify();
|
|
665
|
+
|
|
666
|
+
if (n instanceof Int10) {
|
|
667
|
+
n.sub(80);
|
|
668
|
+
s = '2.' + n.toString();
|
|
669
|
+
} else {
|
|
670
|
+
const m = n < 80 ? n < 40 ? 0 : 1 : 2;
|
|
671
|
+
s = m + '.' + (n - m * 40);
|
|
672
|
+
}
|
|
673
|
+
} else {
|
|
674
|
+
s += '.' + n.toString();
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
if (s.length > maxLength) {
|
|
678
|
+
return stringCut(s, maxLength);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
n = new Int10();
|
|
682
|
+
bits = 0;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
if (bits > 0) {
|
|
687
|
+
s += '.incomplete';
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
return s;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
}
|
|
694
|
+
class ASN1 {
|
|
695
|
+
constructor(stream, header, length, tag, sub) {
|
|
696
|
+
if (!(tag instanceof ASN1Tag)) {
|
|
697
|
+
throw new Error('Invalid tag value.');
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
this.stream = stream;
|
|
701
|
+
this.header = header;
|
|
702
|
+
this.length = length;
|
|
703
|
+
this.tag = tag;
|
|
704
|
+
this.sub = sub;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
typeName() {
|
|
708
|
+
switch (this.tag.tagClass) {
|
|
709
|
+
case 0:
|
|
710
|
+
// universal
|
|
711
|
+
switch (this.tag.tagNumber) {
|
|
712
|
+
case 0x00:
|
|
713
|
+
return 'EOC';
|
|
714
|
+
|
|
715
|
+
case 0x01:
|
|
716
|
+
return 'BOOLEAN';
|
|
717
|
+
|
|
718
|
+
case 0x02:
|
|
719
|
+
return 'INTEGER';
|
|
720
|
+
|
|
721
|
+
case 0x03:
|
|
722
|
+
return 'BIT_STRING';
|
|
723
|
+
|
|
724
|
+
case 0x04:
|
|
725
|
+
return 'OCTET_STRING';
|
|
726
|
+
|
|
727
|
+
case 0x05:
|
|
728
|
+
return 'NULL';
|
|
729
|
+
|
|
730
|
+
case 0x06:
|
|
731
|
+
return 'OBJECT_IDENTIFIER';
|
|
732
|
+
|
|
733
|
+
case 0x07:
|
|
734
|
+
return 'ObjectDescriptor';
|
|
735
|
+
|
|
736
|
+
case 0x08:
|
|
737
|
+
return 'EXTERNAL';
|
|
738
|
+
|
|
739
|
+
case 0x09:
|
|
740
|
+
return 'REAL';
|
|
741
|
+
|
|
742
|
+
case 0x0a:
|
|
743
|
+
return 'ENUMERATED';
|
|
744
|
+
|
|
745
|
+
case 0x0b:
|
|
746
|
+
return 'EMBEDDED_PDV';
|
|
747
|
+
|
|
748
|
+
case 0x0c:
|
|
749
|
+
return 'UTF8String';
|
|
750
|
+
|
|
751
|
+
case 0x10:
|
|
752
|
+
return 'SEQUENCE';
|
|
753
|
+
|
|
754
|
+
case 0x11:
|
|
755
|
+
return 'SET';
|
|
756
|
+
|
|
757
|
+
case 0x12:
|
|
758
|
+
return 'NumericString';
|
|
759
|
+
|
|
760
|
+
case 0x13:
|
|
761
|
+
return 'PrintableString';
|
|
762
|
+
// ASCII subset
|
|
763
|
+
|
|
764
|
+
case 0x14:
|
|
765
|
+
return 'TeletexString';
|
|
766
|
+
// aka T61String
|
|
767
|
+
|
|
768
|
+
case 0x15:
|
|
769
|
+
return 'VideotexString';
|
|
770
|
+
|
|
771
|
+
case 0x16:
|
|
772
|
+
return 'IA5String';
|
|
773
|
+
// ASCII
|
|
774
|
+
|
|
775
|
+
case 0x17:
|
|
776
|
+
return 'UTCTime';
|
|
777
|
+
|
|
778
|
+
case 0x18:
|
|
779
|
+
return 'GeneralizedTime';
|
|
780
|
+
|
|
781
|
+
case 0x19:
|
|
782
|
+
return 'GraphicString';
|
|
783
|
+
|
|
784
|
+
case 0x1a:
|
|
785
|
+
return 'VisibleString';
|
|
786
|
+
// ASCII subset
|
|
787
|
+
|
|
788
|
+
case 0x1b:
|
|
789
|
+
return 'GeneralString';
|
|
790
|
+
|
|
791
|
+
case 0x1c:
|
|
792
|
+
return 'UniversalString';
|
|
793
|
+
|
|
794
|
+
case 0x1e:
|
|
795
|
+
return 'BMPString';
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
return 'Universal_' + this.tag.tagNumber.toString();
|
|
799
|
+
|
|
800
|
+
case 1:
|
|
801
|
+
return 'Application_' + this.tag.tagNumber.toString();
|
|
802
|
+
|
|
803
|
+
case 2:
|
|
804
|
+
return '[' + this.tag.tagNumber.toString() + ']';
|
|
805
|
+
// Context
|
|
806
|
+
|
|
807
|
+
case 3:
|
|
808
|
+
return 'Private_' + this.tag.tagNumber.toString();
|
|
809
|
+
|
|
810
|
+
default:
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
content(maxLength) {
|
|
816
|
+
// a preview of the content (intended for humans)
|
|
817
|
+
if (this.tag === undefined) {
|
|
818
|
+
return null;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
if (maxLength === undefined) {
|
|
822
|
+
maxLength = Infinity;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
const content = this.posContent();
|
|
826
|
+
const len = Math.abs(this.length);
|
|
827
|
+
|
|
828
|
+
if (!this.tag.isUniversal()) {
|
|
829
|
+
if (this.sub !== null) {
|
|
830
|
+
return '(' + this.sub.length + ' elem)';
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
return this.stream.parseOctetString(content, content + len, maxLength);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
switch (this.tag.tagNumber) {
|
|
837
|
+
case 0x01:
|
|
838
|
+
// BOOLEAN
|
|
839
|
+
return this.stream.get(content) === 0 ? 'false' : 'true';
|
|
840
|
+
|
|
841
|
+
case 0x02:
|
|
842
|
+
// INTEGER
|
|
843
|
+
return this.stream.parseInteger(content, content + len);
|
|
844
|
+
|
|
845
|
+
case 0x03:
|
|
846
|
+
// BIT_STRING
|
|
847
|
+
return this.sub ? '(' + this.sub.length + ' elem)' : this.stream.parseBitString(content, content + len, maxLength);
|
|
848
|
+
|
|
849
|
+
case 0x04:
|
|
850
|
+
// OCTET_STRING
|
|
851
|
+
return this.sub ? '(' + this.sub.length + ' elem)' : this.stream.parseOctetString(content, content + len, maxLength);
|
|
852
|
+
// case 0x05: // NULL
|
|
853
|
+
|
|
854
|
+
case 0x06:
|
|
855
|
+
// OBJECT_IDENTIFIER
|
|
856
|
+
return this.stream.parseOID(content, content + len, maxLength);
|
|
857
|
+
// case 0x07: // ObjectDescriptor
|
|
858
|
+
// case 0x08: // EXTERNAL
|
|
859
|
+
// case 0x09: // REAL
|
|
860
|
+
// case 0x0A: // ENUMERATED
|
|
861
|
+
// case 0x0B: // EMBEDDED_PDV
|
|
862
|
+
|
|
863
|
+
case 0x10: // SEQUENCE
|
|
864
|
+
|
|
865
|
+
case 0x11:
|
|
866
|
+
// SET
|
|
867
|
+
if (this.sub !== null) {
|
|
868
|
+
return '(' + this.sub.length + ' elem)';
|
|
869
|
+
} else {
|
|
870
|
+
return '(no elem)';
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
case 0x0c:
|
|
874
|
+
// UTF8String
|
|
875
|
+
return stringCut(this.stream.parseStringUTF(content, content + len), maxLength);
|
|
876
|
+
|
|
877
|
+
case 0x12: // NumericString
|
|
878
|
+
|
|
879
|
+
case 0x13: // PrintableString
|
|
880
|
+
|
|
881
|
+
case 0x14: // TeletexString
|
|
882
|
+
|
|
883
|
+
case 0x15: // VideotexString
|
|
884
|
+
|
|
885
|
+
case 0x16: // IA5String
|
|
886
|
+
// case 0x19: // GraphicString
|
|
887
|
+
// eslint-disable-next-line no-fallthrough
|
|
888
|
+
|
|
889
|
+
case 0x1a:
|
|
890
|
+
// VisibleString
|
|
891
|
+
// case 0x1B: // GeneralString
|
|
892
|
+
// case 0x1C: // UniversalString
|
|
893
|
+
return stringCut(this.stream.parseStringISO(content, content + len), maxLength);
|
|
894
|
+
|
|
895
|
+
case 0x1e:
|
|
896
|
+
// BMPString
|
|
897
|
+
return stringCut(this.stream.parseStringBMP(content, content + len), maxLength);
|
|
898
|
+
|
|
899
|
+
case 0x17: // UTCTime
|
|
900
|
+
|
|
901
|
+
case 0x18:
|
|
902
|
+
// GeneralizedTime
|
|
903
|
+
return this.stream.parseTime(content, content + len, this.tag.tagNumber == 0x17);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
return null;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
toString() {
|
|
910
|
+
return this.typeName() + '@' + this.stream.pos + '[header:' + this.header + ',length:' + this.length + ',sub:' + (this.sub === null ? 'null' : this.sub.length) + ']';
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
toPrettyString(indent) {
|
|
914
|
+
if (indent === undefined) {
|
|
915
|
+
indent = '';
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
let s = indent + this.typeName() + ' @' + this.stream.pos;
|
|
919
|
+
|
|
920
|
+
if (this.length >= 0) {
|
|
921
|
+
s += '+';
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
s += this.length;
|
|
925
|
+
|
|
926
|
+
if (this.tag.tagConstructed) {
|
|
927
|
+
s += ' (constructed)';
|
|
928
|
+
} else if (this.tag.isUniversal() && (this.tag.tagNumber == 0x03 || this.tag.tagNumber == 0x04) && this.sub !== null) {
|
|
929
|
+
s += ' (encapsulates)';
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
s += '\n';
|
|
933
|
+
|
|
934
|
+
if (this.sub !== null) {
|
|
935
|
+
indent += ' ';
|
|
936
|
+
|
|
937
|
+
for (let i = 0, max = this.sub.length; i < max; ++i) {
|
|
938
|
+
s += this.sub[i].toPrettyString(indent);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
return s;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
posStart() {
|
|
946
|
+
return this.stream.pos;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
posContent() {
|
|
950
|
+
return this.stream.pos + this.header;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
posEnd() {
|
|
954
|
+
return this.stream.pos + this.header + Math.abs(this.length);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
toHexString() {
|
|
958
|
+
return this.stream.hexDump(this.posStart(), this.posEnd(), true);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
static decodeLength(stream) {
|
|
962
|
+
let buf = stream.get();
|
|
963
|
+
const len = buf & 0x7f;
|
|
964
|
+
|
|
965
|
+
if (len == buf) {
|
|
966
|
+
return len;
|
|
967
|
+
} // no reason to use Int10, as it would be a huge buffer anyways
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
if (len > 6) {
|
|
971
|
+
throw new Error('Length over 48 bits not supported at position ' + (stream.pos - 1));
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
if (len === 0) {
|
|
975
|
+
return null;
|
|
976
|
+
} // undefined
|
|
977
|
+
|
|
978
|
+
|
|
979
|
+
buf = 0;
|
|
980
|
+
|
|
981
|
+
for (let i = 0; i < len; ++i) {
|
|
982
|
+
buf = buf * 256 + stream.get();
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
return buf;
|
|
986
|
+
}
|
|
987
|
+
/**
|
|
988
|
+
* Retrieve the hexadecimal value (as a string) of the current ASN.1 element
|
|
989
|
+
* @returns {string}
|
|
990
|
+
* @public
|
|
991
|
+
*/
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
getHexStringValue() {
|
|
995
|
+
const hexString = this.toHexString();
|
|
996
|
+
const offset = this.header * 2;
|
|
997
|
+
const length = this.length * 2;
|
|
998
|
+
return hexString.substr(offset, length);
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
static decode(str) {
|
|
1002
|
+
let stream;
|
|
1003
|
+
|
|
1004
|
+
if (!(str instanceof Stream)) {
|
|
1005
|
+
stream = new Stream(str, 0);
|
|
1006
|
+
} else {
|
|
1007
|
+
stream = str;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
const streamStart = new Stream(stream);
|
|
1011
|
+
const tag = new ASN1Tag(stream);
|
|
1012
|
+
let len = ASN1.decodeLength(stream);
|
|
1013
|
+
const start = stream.pos;
|
|
1014
|
+
const header = start - streamStart.pos;
|
|
1015
|
+
let sub = null;
|
|
1016
|
+
|
|
1017
|
+
const getSub = function getSub() {
|
|
1018
|
+
const ret = [];
|
|
1019
|
+
|
|
1020
|
+
if (len !== null) {
|
|
1021
|
+
// definite length
|
|
1022
|
+
const end = start + len;
|
|
1023
|
+
|
|
1024
|
+
while (stream.pos < end) {
|
|
1025
|
+
ret[ret.length] = ASN1.decode(stream);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
if (stream.pos != end) {
|
|
1029
|
+
throw new Error('Content size is not correct for container starting at offset ' + start);
|
|
1030
|
+
}
|
|
1031
|
+
} else {
|
|
1032
|
+
// undefined length
|
|
1033
|
+
try {
|
|
1034
|
+
for (;;) {
|
|
1035
|
+
const s = ASN1.decode(stream);
|
|
1036
|
+
|
|
1037
|
+
if (s.tag.isEOC()) {
|
|
1038
|
+
break;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
ret[ret.length] = s;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
len = start - stream.pos; // undefined lengths are represented as negative values
|
|
1045
|
+
} catch (e) {
|
|
1046
|
+
throw new Error('Exception while decoding undefined length content: ' + e);
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
return ret;
|
|
1051
|
+
};
|
|
1052
|
+
|
|
1053
|
+
if (tag.tagConstructed) {
|
|
1054
|
+
// must have valid content
|
|
1055
|
+
sub = getSub();
|
|
1056
|
+
} else if (tag.isUniversal() && (tag.tagNumber == 0x03 || tag.tagNumber == 0x04)) {
|
|
1057
|
+
// sometimes BitString and OctetString are used to encapsulate ASN.1
|
|
1058
|
+
try {
|
|
1059
|
+
if (tag.tagNumber == 0x03) {
|
|
1060
|
+
if (stream.get() != 0) {
|
|
1061
|
+
throw new Error('BIT STRINGs with unused bits cannot encapsulate.');
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
sub = getSub();
|
|
1066
|
+
|
|
1067
|
+
for (let i = 0; i < sub.length; ++i) {
|
|
1068
|
+
if (sub[i].tag.isEOC()) {
|
|
1069
|
+
throw new Error('EOC is not supposed to be actual content.');
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
} catch (e) {
|
|
1073
|
+
// but silently ignore when they don't
|
|
1074
|
+
sub = null;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
if (len === null) {
|
|
1079
|
+
throw new Error("We can't skip over an invalid tag with undefined length at offset " + start);
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
if (sub === null) {
|
|
1083
|
+
if (len === null) {
|
|
1084
|
+
throw new Error("We can't skip over an invalid tag with undefined length at offset " + start);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
stream.pos = start + Math.abs(len);
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
return new ASN1(streamStart, header, len, tag, sub);
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
}
|
|
1094
|
+
class ASN1Tag {
|
|
1095
|
+
constructor(stream) {
|
|
1096
|
+
let buf = stream.get();
|
|
1097
|
+
this.tagClass = buf >> 6;
|
|
1098
|
+
this.tagConstructed = (buf & 0x20) !== 0;
|
|
1099
|
+
this.tagNumber = buf & 0x1f;
|
|
1100
|
+
|
|
1101
|
+
if (this.tagNumber == 0x1f) {
|
|
1102
|
+
// long tag
|
|
1103
|
+
const n = new Int10();
|
|
1104
|
+
|
|
1105
|
+
do {
|
|
1106
|
+
buf = stream.get();
|
|
1107
|
+
n.mulAdd(128, buf & 0x7f);
|
|
1108
|
+
} while (buf & 0x80);
|
|
1109
|
+
|
|
1110
|
+
this.tagNumber = n.simplify();
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
isUniversal() {
|
|
1115
|
+
return this.tagClass === 0x00;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
isEOC() {
|
|
1119
|
+
return this.tagClass === 0x00 && this.tagNumber === 0x00;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// Copyright (c) 2005 Tom Wu
|
|
1125
|
+
|
|
1126
|
+
let dbits; // JavaScript engine analysis
|
|
1127
|
+
|
|
1128
|
+
const canary = 0xdeadbeefcafe;
|
|
1129
|
+
const j_lm = (canary & 0xffffff) == 0xefcafe; // am: Compute w_j += (x*this_i), propagate carries,
|
|
1130
|
+
// c is initial carry, returns final carry.
|
|
1131
|
+
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
|
|
1132
|
+
// We need to select the fastest one that works in this environment.
|
|
1133
|
+
|
|
1134
|
+
const inBrowser = typeof navigator !== 'undefined';
|
|
1135
|
+
const isIE = inBrowser && j_lm && navigator.appName === 'Microsoft Internet Explorer';
|
|
1136
|
+
const isNetscapeOrWx = (inBrowser && navigator.appName !== 'Netscape' || typeof wx !== 'undefined');
|
|
1137
|
+
|
|
1138
|
+
if (isIE) {
|
|
1139
|
+
dbits = 30;
|
|
1140
|
+
} else if (isNetscapeOrWx) {
|
|
1141
|
+
dbits = 26;
|
|
1142
|
+
} else {
|
|
1143
|
+
dbits = 28;
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
const BI_FP = 52; //#region
|
|
1147
|
+
|
|
1148
|
+
const lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997];
|
|
1149
|
+
const lplim = (1 << 26) / lowprimes[lowprimes.length - 1]; //#endregion
|
|
1150
|
+
// (public) Constructor
|
|
1151
|
+
|
|
1152
|
+
class BigInteger {
|
|
1153
|
+
constructor(a, b, c) {
|
|
1154
|
+
this.DB = dbits;
|
|
1155
|
+
this.DM = (1 << dbits) - 1;
|
|
1156
|
+
this.DV = 1 << dbits;
|
|
1157
|
+
this.FV = Math.pow(2, BI_FP);
|
|
1158
|
+
this.F1 = BI_FP - dbits;
|
|
1159
|
+
this.F2 = 2 * dbits - BI_FP;
|
|
1160
|
+
|
|
1161
|
+
if (a != null) {
|
|
1162
|
+
if ('number' == typeof a) {
|
|
1163
|
+
if (typeof b !== 'undefined') {
|
|
1164
|
+
this.fromNumber(a, b, c);
|
|
1165
|
+
}
|
|
1166
|
+
} else if (b == null && 'string' != typeof a) {
|
|
1167
|
+
this.fromString(a, 256);
|
|
1168
|
+
} else {
|
|
1169
|
+
this.fromString(a, b);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
} //#region PUBLIC
|
|
1173
|
+
// (public) return string representation in given radix
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
toString(b) {
|
|
1177
|
+
if (this.s < 0) {
|
|
1178
|
+
return '-' + this.negate().toString(b);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
let k;
|
|
1182
|
+
|
|
1183
|
+
if (b == 16) {
|
|
1184
|
+
k = 4;
|
|
1185
|
+
} else if (b == 8) {
|
|
1186
|
+
k = 3;
|
|
1187
|
+
} else if (b == 2) {
|
|
1188
|
+
k = 1;
|
|
1189
|
+
} else if (b == 32) {
|
|
1190
|
+
k = 5;
|
|
1191
|
+
} else if (b == 4) {
|
|
1192
|
+
k = 2;
|
|
1193
|
+
} else {
|
|
1194
|
+
return this.toRadix(b);
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
const km = (1 << k) - 1;
|
|
1198
|
+
let d;
|
|
1199
|
+
let m = false;
|
|
1200
|
+
let r = '';
|
|
1201
|
+
let i = this.t;
|
|
1202
|
+
let p = this.DB - i * this.DB % k;
|
|
1203
|
+
|
|
1204
|
+
if (i-- > 0) {
|
|
1205
|
+
if (p < this.DB && (d = this[i] >> p) > 0) {
|
|
1206
|
+
m = true;
|
|
1207
|
+
r = int2char(d);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
while (i >= 0) {
|
|
1211
|
+
if (p < k) {
|
|
1212
|
+
d = (this[i] & (1 << p) - 1) << k - p;
|
|
1213
|
+
d |= this[--i] >> (p += this.DB - k);
|
|
1214
|
+
} else {
|
|
1215
|
+
d = this[i] >> (p -= k) & km;
|
|
1216
|
+
|
|
1217
|
+
if (p <= 0) {
|
|
1218
|
+
p += this.DB;
|
|
1219
|
+
--i;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
if (d > 0) {
|
|
1224
|
+
m = true;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
if (m) {
|
|
1228
|
+
r += int2char(d);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
return m ? r : '0';
|
|
1234
|
+
} // (public) -this
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
negate() {
|
|
1238
|
+
const r = nbi();
|
|
1239
|
+
BigInteger.ZERO.subTo(this, r);
|
|
1240
|
+
return r;
|
|
1241
|
+
} // (public) |this|
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
abs() {
|
|
1245
|
+
return this.s < 0 ? this.negate() : this;
|
|
1246
|
+
} // (public) return + if this > a, - if this < a, 0 if equal
|
|
1247
|
+
|
|
1248
|
+
|
|
1249
|
+
compareTo(a) {
|
|
1250
|
+
let r = this.s - a.s;
|
|
1251
|
+
|
|
1252
|
+
if (r != 0) {
|
|
1253
|
+
return r;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
let i = this.t;
|
|
1257
|
+
r = i - a.t;
|
|
1258
|
+
|
|
1259
|
+
if (r != 0) {
|
|
1260
|
+
return this.s < 0 ? -r : r;
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
while (--i >= 0) {
|
|
1264
|
+
if ((r = this[i] - a[i]) != 0) {
|
|
1265
|
+
return r;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
return 0;
|
|
1270
|
+
} // (public) return the number of bits in "this"
|
|
1271
|
+
|
|
1272
|
+
|
|
1273
|
+
bitLength() {
|
|
1274
|
+
if (this.t <= 0) {
|
|
1275
|
+
return 0;
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ this.s & this.DM);
|
|
1279
|
+
} // (public) this mod a
|
|
1280
|
+
|
|
1281
|
+
|
|
1282
|
+
mod(a) {
|
|
1283
|
+
const r = nbi();
|
|
1284
|
+
this.abs().divRemTo(a, null, r);
|
|
1285
|
+
|
|
1286
|
+
if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) {
|
|
1287
|
+
a.subTo(r, r);
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
return r;
|
|
1291
|
+
} // (public) this^e % m, 0 <= e < 2^32
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
modPowInt(e, m) {
|
|
1295
|
+
let z;
|
|
1296
|
+
|
|
1297
|
+
if (e < 256 || m.isEven()) {
|
|
1298
|
+
z = new Classic(m);
|
|
1299
|
+
} else {
|
|
1300
|
+
z = new Montgomery(m);
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
return this.exp(e, z);
|
|
1304
|
+
} // (public)
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
clone() {
|
|
1308
|
+
const r = nbi();
|
|
1309
|
+
this.copyTo(r);
|
|
1310
|
+
return r;
|
|
1311
|
+
} // (public) return value as integer
|
|
1312
|
+
|
|
1313
|
+
|
|
1314
|
+
intValue() {
|
|
1315
|
+
if (this.s < 0) {
|
|
1316
|
+
if (this.t == 1) {
|
|
1317
|
+
return this[0] - this.DV;
|
|
1318
|
+
} else if (this.t == 0) {
|
|
1319
|
+
return -1;
|
|
1320
|
+
}
|
|
1321
|
+
} else if (this.t == 1) {
|
|
1322
|
+
return this[0];
|
|
1323
|
+
} else if (this.t == 0) {
|
|
1324
|
+
return 0;
|
|
1325
|
+
} // assumes 16 < DB < 32
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
return (this[1] & (1 << 32 - this.DB) - 1) << this.DB | this[0];
|
|
1329
|
+
} // (public) return value as byte
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
byteValue() {
|
|
1333
|
+
return this.t == 0 ? this.s : this[0] << 24 >> 24;
|
|
1334
|
+
} // (public) return value as short (assumes DB>=16)
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
shortValue() {
|
|
1338
|
+
return this.t == 0 ? this.s : this[0] << 16 >> 16;
|
|
1339
|
+
} // (public) 0 if this == 0, 1 if this > 0
|
|
1340
|
+
|
|
1341
|
+
|
|
1342
|
+
signum() {
|
|
1343
|
+
if (this.s < 0) {
|
|
1344
|
+
return -1;
|
|
1345
|
+
} else if (this.t <= 0 || this.t == 1 && this[0] <= 0) {
|
|
1346
|
+
return 0;
|
|
1347
|
+
} else {
|
|
1348
|
+
return 1;
|
|
1349
|
+
}
|
|
1350
|
+
} // (public) convert to bigendian byte array
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
toByteArray() {
|
|
1354
|
+
let i = this.t;
|
|
1355
|
+
const r = [];
|
|
1356
|
+
r[0] = this.s;
|
|
1357
|
+
let p = this.DB - i * this.DB % 8;
|
|
1358
|
+
let d;
|
|
1359
|
+
let k = 0;
|
|
1360
|
+
|
|
1361
|
+
if (i-- > 0) {
|
|
1362
|
+
if (p < this.DB && (d = this[i] >> p) != (this.s & this.DM) >> p) {
|
|
1363
|
+
r[k++] = d | this.s << this.DB - p;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
while (i >= 0) {
|
|
1367
|
+
if (p < 8) {
|
|
1368
|
+
d = (this[i] & (1 << p) - 1) << 8 - p;
|
|
1369
|
+
d |= this[--i] >> (p += this.DB - 8);
|
|
1370
|
+
} else {
|
|
1371
|
+
d = this[i] >> (p -= 8) & 0xff;
|
|
1372
|
+
|
|
1373
|
+
if (p <= 0) {
|
|
1374
|
+
p += this.DB;
|
|
1375
|
+
--i;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
if ((d & 0x80) != 0) {
|
|
1380
|
+
d |= -256;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
if (k == 0 && (this.s & 0x80) != (d & 0x80)) {
|
|
1384
|
+
++k;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
if (k > 0 || d != this.s) {
|
|
1388
|
+
r[k++] = d;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
return r;
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
equals(a) {
|
|
1397
|
+
return this.compareTo(a) == 0;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
min(a) {
|
|
1401
|
+
return this.compareTo(a) < 0 ? this : a;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
max(a) {
|
|
1405
|
+
return this.compareTo(a) > 0 ? this : a;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
and(a) {
|
|
1409
|
+
const r = nbi();
|
|
1410
|
+
this.bitwiseTo(a, op_and, r);
|
|
1411
|
+
return r;
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
or(a) {
|
|
1415
|
+
const r = nbi();
|
|
1416
|
+
this.bitwiseTo(a, op_or, r);
|
|
1417
|
+
return r;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
xor(a) {
|
|
1421
|
+
const r = nbi();
|
|
1422
|
+
this.bitwiseTo(a, op_xor, r);
|
|
1423
|
+
return r;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
andNot(a) {
|
|
1427
|
+
const r = nbi();
|
|
1428
|
+
this.bitwiseTo(a, op_andnot, r);
|
|
1429
|
+
return r;
|
|
1430
|
+
} // (public) ~this
|
|
1431
|
+
|
|
1432
|
+
|
|
1433
|
+
not() {
|
|
1434
|
+
const r = nbi();
|
|
1435
|
+
|
|
1436
|
+
for (let i = 0; i < this.t; ++i) {
|
|
1437
|
+
r[i] = this.DM & ~this[i];
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
r.t = this.t;
|
|
1441
|
+
r.s = ~this.s;
|
|
1442
|
+
return r;
|
|
1443
|
+
} // (public) this << n
|
|
1444
|
+
|
|
1445
|
+
|
|
1446
|
+
shiftLeft(n) {
|
|
1447
|
+
const r = nbi();
|
|
1448
|
+
|
|
1449
|
+
if (n < 0) {
|
|
1450
|
+
this.rShiftTo(-n, r);
|
|
1451
|
+
} else {
|
|
1452
|
+
this.lShiftTo(n, r);
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
return r;
|
|
1456
|
+
} // (public) this >> n
|
|
1457
|
+
|
|
1458
|
+
|
|
1459
|
+
shiftRight(n) {
|
|
1460
|
+
const r = nbi();
|
|
1461
|
+
|
|
1462
|
+
if (n < 0) {
|
|
1463
|
+
this.lShiftTo(-n, r);
|
|
1464
|
+
} else {
|
|
1465
|
+
this.rShiftTo(n, r);
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
return r;
|
|
1469
|
+
} // (public) returns index of lowest 1-bit (or -1 if none)
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
getLowestSetBit() {
|
|
1473
|
+
for (let i = 0; i < this.t; ++i) {
|
|
1474
|
+
if (this[i] != 0) {
|
|
1475
|
+
return i * this.DB + lbit(this[i]);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
if (this.s < 0) {
|
|
1480
|
+
return this.t * this.DB;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
return -1;
|
|
1484
|
+
} // (public) return number of set bits
|
|
1485
|
+
|
|
1486
|
+
|
|
1487
|
+
bitCount() {
|
|
1488
|
+
let r = 0;
|
|
1489
|
+
const x = this.s & this.DM;
|
|
1490
|
+
|
|
1491
|
+
for (let i = 0; i < this.t; ++i) {
|
|
1492
|
+
r += cbit(this[i] ^ x);
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
return r;
|
|
1496
|
+
} // (public) true iff nth bit is set
|
|
1497
|
+
|
|
1498
|
+
|
|
1499
|
+
testBit(n) {
|
|
1500
|
+
const j = Math.floor(n / this.DB);
|
|
1501
|
+
|
|
1502
|
+
if (j >= this.t) {
|
|
1503
|
+
return this.s != 0;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
return (this[j] & 1 << n % this.DB) != 0;
|
|
1507
|
+
} // (public) this | (1<<n)
|
|
1508
|
+
|
|
1509
|
+
|
|
1510
|
+
setBit(n) {
|
|
1511
|
+
return this.changeBit(n, op_or);
|
|
1512
|
+
} // (public) this & ~(1<<n)
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
|
+
clearBit(n) {
|
|
1516
|
+
return this.changeBit(n, op_andnot);
|
|
1517
|
+
} // (public) this ^ (1<<n)
|
|
1518
|
+
|
|
1519
|
+
|
|
1520
|
+
flipBit(n) {
|
|
1521
|
+
return this.changeBit(n, op_xor);
|
|
1522
|
+
} // (public) this + a
|
|
1523
|
+
|
|
1524
|
+
|
|
1525
|
+
add(a) {
|
|
1526
|
+
const r = nbi();
|
|
1527
|
+
this.addTo(a, r);
|
|
1528
|
+
return r;
|
|
1529
|
+
} // (public) this - a
|
|
1530
|
+
|
|
1531
|
+
|
|
1532
|
+
subtract(a) {
|
|
1533
|
+
const r = nbi();
|
|
1534
|
+
this.subTo(a, r);
|
|
1535
|
+
return r;
|
|
1536
|
+
} // (public) this * a
|
|
1537
|
+
|
|
1538
|
+
|
|
1539
|
+
multiply(a) {
|
|
1540
|
+
const r = nbi();
|
|
1541
|
+
this.multiplyTo(a, r);
|
|
1542
|
+
return r;
|
|
1543
|
+
} // (public) this / a
|
|
1544
|
+
|
|
1545
|
+
|
|
1546
|
+
divide(a) {
|
|
1547
|
+
const r = nbi();
|
|
1548
|
+
this.divRemTo(a, r, null);
|
|
1549
|
+
return r;
|
|
1550
|
+
} // (public) this % a
|
|
1551
|
+
|
|
1552
|
+
|
|
1553
|
+
remainder(a) {
|
|
1554
|
+
const r = nbi();
|
|
1555
|
+
this.divRemTo(a, null, r);
|
|
1556
|
+
return r;
|
|
1557
|
+
} // (public) [this/a,this%a]
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
divideAndRemainder(a) {
|
|
1561
|
+
const q = nbi();
|
|
1562
|
+
const r = nbi();
|
|
1563
|
+
this.divRemTo(a, q, r);
|
|
1564
|
+
return [q, r];
|
|
1565
|
+
} // (public) this^e % m (HAC 14.85)
|
|
1566
|
+
|
|
1567
|
+
|
|
1568
|
+
modPow(e, m) {
|
|
1569
|
+
let i = e.bitLength();
|
|
1570
|
+
let k;
|
|
1571
|
+
let r = nbv(1);
|
|
1572
|
+
let z;
|
|
1573
|
+
|
|
1574
|
+
if (i <= 0) {
|
|
1575
|
+
return r;
|
|
1576
|
+
} else if (i < 18) {
|
|
1577
|
+
k = 1;
|
|
1578
|
+
} else if (i < 48) {
|
|
1579
|
+
k = 3;
|
|
1580
|
+
} else if (i < 144) {
|
|
1581
|
+
k = 4;
|
|
1582
|
+
} else if (i < 768) {
|
|
1583
|
+
k = 5;
|
|
1584
|
+
} else {
|
|
1585
|
+
k = 6;
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
if (i < 8) {
|
|
1589
|
+
z = new Classic(m);
|
|
1590
|
+
} else if (m.isEven()) {
|
|
1591
|
+
z = new Barrett(m);
|
|
1592
|
+
} else {
|
|
1593
|
+
z = new Montgomery(m);
|
|
1594
|
+
} // precomputation
|
|
1595
|
+
|
|
1596
|
+
|
|
1597
|
+
const g = [];
|
|
1598
|
+
let n = 3;
|
|
1599
|
+
const k1 = k - 1;
|
|
1600
|
+
const km = (1 << k) - 1;
|
|
1601
|
+
g[1] = z.convert(this);
|
|
1602
|
+
|
|
1603
|
+
if (k > 1) {
|
|
1604
|
+
const g2 = nbi();
|
|
1605
|
+
z.sqrTo(g[1], g2);
|
|
1606
|
+
|
|
1607
|
+
while (n <= km) {
|
|
1608
|
+
g[n] = nbi();
|
|
1609
|
+
z.mulTo(g2, g[n - 2], g[n]);
|
|
1610
|
+
n += 2;
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
let j = e.t - 1;
|
|
1615
|
+
let w;
|
|
1616
|
+
let is1 = true;
|
|
1617
|
+
let r2 = nbi();
|
|
1618
|
+
let t;
|
|
1619
|
+
i = nbits(e[j]) - 1;
|
|
1620
|
+
|
|
1621
|
+
while (j >= 0) {
|
|
1622
|
+
if (i >= k1) {
|
|
1623
|
+
w = e[j] >> i - k1 & km;
|
|
1624
|
+
} else {
|
|
1625
|
+
w = (e[j] & (1 << i + 1) - 1) << k1 - i;
|
|
1626
|
+
|
|
1627
|
+
if (j > 0) {
|
|
1628
|
+
w |= e[j - 1] >> this.DB + i - k1;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
n = k;
|
|
1633
|
+
|
|
1634
|
+
while ((w & 1) == 0) {
|
|
1635
|
+
w >>= 1;
|
|
1636
|
+
--n;
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
if ((i -= n) < 0) {
|
|
1640
|
+
i += this.DB;
|
|
1641
|
+
--j;
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
if (is1) {
|
|
1645
|
+
// ret == 1, don't bother squaring or multiplying it
|
|
1646
|
+
g[w].copyTo(r);
|
|
1647
|
+
is1 = false;
|
|
1648
|
+
} else {
|
|
1649
|
+
while (n > 1) {
|
|
1650
|
+
z.sqrTo(r, r2);
|
|
1651
|
+
z.sqrTo(r2, r);
|
|
1652
|
+
n -= 2;
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
if (n > 0) {
|
|
1656
|
+
z.sqrTo(r, r2);
|
|
1657
|
+
} else {
|
|
1658
|
+
t = r;
|
|
1659
|
+
r = r2;
|
|
1660
|
+
r2 = t;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
z.mulTo(r2, g[w], r);
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
while (j >= 0 && (e[j] & 1 << i) == 0) {
|
|
1667
|
+
z.sqrTo(r, r2);
|
|
1668
|
+
t = r;
|
|
1669
|
+
r = r2;
|
|
1670
|
+
r2 = t;
|
|
1671
|
+
|
|
1672
|
+
if (--i < 0) {
|
|
1673
|
+
i = this.DB - 1;
|
|
1674
|
+
--j;
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
return z.revert(r);
|
|
1680
|
+
} // (public) 1/this % m (HAC 14.61)
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
modInverse(m) {
|
|
1684
|
+
const ac = m.isEven();
|
|
1685
|
+
|
|
1686
|
+
if (this.isEven() && ac || m.signum() == 0) {
|
|
1687
|
+
return BigInteger.ZERO;
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
const u = m.clone();
|
|
1691
|
+
const v = this.clone();
|
|
1692
|
+
const a = nbv(1);
|
|
1693
|
+
const b = nbv(0);
|
|
1694
|
+
const c = nbv(0);
|
|
1695
|
+
const d = nbv(1);
|
|
1696
|
+
|
|
1697
|
+
while (u.signum() != 0) {
|
|
1698
|
+
while (u.isEven()) {
|
|
1699
|
+
u.rShiftTo(1, u);
|
|
1700
|
+
|
|
1701
|
+
if (ac) {
|
|
1702
|
+
if (!a.isEven() || !b.isEven()) {
|
|
1703
|
+
a.addTo(this, a);
|
|
1704
|
+
b.subTo(m, b);
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
a.rShiftTo(1, a);
|
|
1708
|
+
} else if (!b.isEven()) {
|
|
1709
|
+
b.subTo(m, b);
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
b.rShiftTo(1, b);
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
while (v.isEven()) {
|
|
1716
|
+
v.rShiftTo(1, v);
|
|
1717
|
+
|
|
1718
|
+
if (ac) {
|
|
1719
|
+
if (!c.isEven() || !d.isEven()) {
|
|
1720
|
+
c.addTo(this, c);
|
|
1721
|
+
d.subTo(m, d);
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
c.rShiftTo(1, c);
|
|
1725
|
+
} else if (!d.isEven()) {
|
|
1726
|
+
d.subTo(m, d);
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
d.rShiftTo(1, d);
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
if (u.compareTo(v) >= 0) {
|
|
1733
|
+
u.subTo(v, u);
|
|
1734
|
+
|
|
1735
|
+
if (ac) {
|
|
1736
|
+
a.subTo(c, a);
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
b.subTo(d, b);
|
|
1740
|
+
} else {
|
|
1741
|
+
v.subTo(u, v);
|
|
1742
|
+
|
|
1743
|
+
if (ac) {
|
|
1744
|
+
c.subTo(a, c);
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
d.subTo(b, d);
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
if (v.compareTo(BigInteger.ONE) != 0) {
|
|
1752
|
+
return BigInteger.ZERO;
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
if (d.compareTo(m) >= 0) {
|
|
1756
|
+
return d.subtract(m);
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
if (d.signum() < 0) {
|
|
1760
|
+
d.addTo(m, d);
|
|
1761
|
+
} else {
|
|
1762
|
+
return d;
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
if (d.signum() < 0) {
|
|
1766
|
+
return d.add(m);
|
|
1767
|
+
} else {
|
|
1768
|
+
return d;
|
|
1769
|
+
}
|
|
1770
|
+
} // (public) this^e
|
|
1771
|
+
|
|
1772
|
+
|
|
1773
|
+
pow(e) {
|
|
1774
|
+
return this.exp(e, new NullExp());
|
|
1775
|
+
} // (public) gcd(this,a) (HAC 14.54)
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
gcd(a) {
|
|
1779
|
+
let x = this.s < 0 ? this.negate() : this.clone();
|
|
1780
|
+
let y = a.s < 0 ? a.negate() : a.clone();
|
|
1781
|
+
|
|
1782
|
+
if (x.compareTo(y) < 0) {
|
|
1783
|
+
const t = x;
|
|
1784
|
+
x = y;
|
|
1785
|
+
y = t;
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
let i = x.getLowestSetBit();
|
|
1789
|
+
let g = y.getLowestSetBit();
|
|
1790
|
+
|
|
1791
|
+
if (g < 0) {
|
|
1792
|
+
return x;
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
if (i < g) {
|
|
1796
|
+
g = i;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
if (g > 0) {
|
|
1800
|
+
x.rShiftTo(g, x);
|
|
1801
|
+
y.rShiftTo(g, y);
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
while (x.signum() > 0) {
|
|
1805
|
+
if ((i = x.getLowestSetBit()) > 0) {
|
|
1806
|
+
x.rShiftTo(i, x);
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
if ((i = y.getLowestSetBit()) > 0) {
|
|
1810
|
+
y.rShiftTo(i, y);
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
if (x.compareTo(y) >= 0) {
|
|
1814
|
+
x.subTo(y, x);
|
|
1815
|
+
x.rShiftTo(1, x);
|
|
1816
|
+
} else {
|
|
1817
|
+
y.subTo(x, y);
|
|
1818
|
+
y.rShiftTo(1, y);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
if (g > 0) {
|
|
1823
|
+
y.lShiftTo(g, y);
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
return y;
|
|
1827
|
+
} // (public) test primality with certainty >= 1-.5^t
|
|
1828
|
+
|
|
1829
|
+
|
|
1830
|
+
isProbablePrime(t) {
|
|
1831
|
+
let i;
|
|
1832
|
+
const x = this.abs();
|
|
1833
|
+
|
|
1834
|
+
if (x.t == 1 && x[0] <= lowprimes[lowprimes.length - 1]) {
|
|
1835
|
+
for (i = 0; i < lowprimes.length; ++i) {
|
|
1836
|
+
if (x[0] == lowprimes[i]) {
|
|
1837
|
+
return true;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
return false;
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
if (x.isEven()) {
|
|
1845
|
+
return false;
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
i = 1;
|
|
1849
|
+
|
|
1850
|
+
while (i < lowprimes.length) {
|
|
1851
|
+
let m = lowprimes[i];
|
|
1852
|
+
let j = i + 1;
|
|
1853
|
+
|
|
1854
|
+
while (j < lowprimes.length && m < lplim) {
|
|
1855
|
+
m *= lowprimes[j++];
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
m = x.modInt(m);
|
|
1859
|
+
|
|
1860
|
+
while (i < j) {
|
|
1861
|
+
if (m % lowprimes[i++] == 0) {
|
|
1862
|
+
return false;
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
|
|
1867
|
+
return x.millerRabin(t);
|
|
1868
|
+
} //#endregion PUBLIC
|
|
1869
|
+
//#region PROTECTED
|
|
1870
|
+
// (protected) copy this to r
|
|
1871
|
+
|
|
1872
|
+
|
|
1873
|
+
copyTo(r) {
|
|
1874
|
+
for (let i = this.t - 1; i >= 0; --i) {
|
|
1875
|
+
r[i] = this[i];
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
r.t = this.t;
|
|
1879
|
+
r.s = this.s;
|
|
1880
|
+
} // (protected) set from integer value x, -DV <= x < DV
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
fromInt(x) {
|
|
1884
|
+
this.t = 1;
|
|
1885
|
+
this.s = x < 0 ? -1 : 0;
|
|
1886
|
+
|
|
1887
|
+
if (x > 0) {
|
|
1888
|
+
this[0] = x;
|
|
1889
|
+
} else if (x < -1) {
|
|
1890
|
+
this[0] = x + this.DV;
|
|
1891
|
+
} else {
|
|
1892
|
+
this.t = 0;
|
|
1893
|
+
}
|
|
1894
|
+
} // (protected) set from string and radix
|
|
1895
|
+
|
|
1896
|
+
|
|
1897
|
+
fromString(s, b) {
|
|
1898
|
+
let k;
|
|
1899
|
+
|
|
1900
|
+
if (b == 16) {
|
|
1901
|
+
k = 4;
|
|
1902
|
+
} else if (b == 8) {
|
|
1903
|
+
k = 3;
|
|
1904
|
+
} else if (b == 256) {
|
|
1905
|
+
k = 8;
|
|
1906
|
+
/* byte array */
|
|
1907
|
+
} else if (b == 2) {
|
|
1908
|
+
k = 1;
|
|
1909
|
+
} else if (b == 32) {
|
|
1910
|
+
k = 5;
|
|
1911
|
+
} else if (b == 4) {
|
|
1912
|
+
k = 2;
|
|
1913
|
+
} else {
|
|
1914
|
+
this.fromRadix(s, b);
|
|
1915
|
+
return;
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
this.t = 0;
|
|
1919
|
+
this.s = 0;
|
|
1920
|
+
let i = s.length;
|
|
1921
|
+
let mi = false;
|
|
1922
|
+
let sh = 0;
|
|
1923
|
+
|
|
1924
|
+
while (--i >= 0) {
|
|
1925
|
+
const x = k == 8 ? +s[i] & 0xff : intAt(s, i);
|
|
1926
|
+
|
|
1927
|
+
if (x < 0) {
|
|
1928
|
+
if (s.charAt(i) == '-') {
|
|
1929
|
+
mi = true;
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
continue;
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
mi = false;
|
|
1936
|
+
|
|
1937
|
+
if (sh == 0) {
|
|
1938
|
+
this[this.t++] = x;
|
|
1939
|
+
} else if (sh + k > this.DB) {
|
|
1940
|
+
this[this.t - 1] |= (x & (1 << this.DB - sh) - 1) << sh;
|
|
1941
|
+
this[this.t++] = x >> this.DB - sh;
|
|
1942
|
+
} else {
|
|
1943
|
+
this[this.t - 1] |= x << sh;
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
sh += k;
|
|
1947
|
+
|
|
1948
|
+
if (sh >= this.DB) {
|
|
1949
|
+
sh -= this.DB;
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
if (k == 8 && (+s[0] & 0x80) != 0) {
|
|
1954
|
+
this.s = -1;
|
|
1955
|
+
|
|
1956
|
+
if (sh > 0) {
|
|
1957
|
+
this[this.t - 1] |= (1 << this.DB - sh) - 1 << sh;
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
this.clamp();
|
|
1962
|
+
|
|
1963
|
+
if (mi) {
|
|
1964
|
+
BigInteger.ZERO.subTo(this, this);
|
|
1965
|
+
}
|
|
1966
|
+
} // (protected) clamp off excess high words
|
|
1967
|
+
|
|
1968
|
+
|
|
1969
|
+
clamp() {
|
|
1970
|
+
const c = this.s & this.DM;
|
|
1971
|
+
|
|
1972
|
+
while (this.t > 0 && this[this.t - 1] == c) {
|
|
1973
|
+
--this.t;
|
|
1974
|
+
}
|
|
1975
|
+
} // (protected) r = this << n*DB
|
|
1976
|
+
|
|
1977
|
+
|
|
1978
|
+
dlShiftTo(n, r) {
|
|
1979
|
+
let i;
|
|
1980
|
+
|
|
1981
|
+
for (i = this.t - 1; i >= 0; --i) {
|
|
1982
|
+
r[i + n] = this[i];
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
for (i = n - 1; i >= 0; --i) {
|
|
1986
|
+
r[i] = 0;
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
r.t = this.t + n;
|
|
1990
|
+
r.s = this.s;
|
|
1991
|
+
} // (protected) r = this >> n*DB
|
|
1992
|
+
|
|
1993
|
+
|
|
1994
|
+
drShiftTo(n, r) {
|
|
1995
|
+
for (let i = n; i < this.t; ++i) {
|
|
1996
|
+
r[i - n] = this[i];
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
r.t = Math.max(this.t - n, 0);
|
|
2000
|
+
r.s = this.s;
|
|
2001
|
+
} // (protected) r = this << n
|
|
2002
|
+
|
|
2003
|
+
|
|
2004
|
+
lShiftTo(n, r) {
|
|
2005
|
+
const bs = n % this.DB;
|
|
2006
|
+
const cbs = this.DB - bs;
|
|
2007
|
+
const bm = (1 << cbs) - 1;
|
|
2008
|
+
const ds = Math.floor(n / this.DB);
|
|
2009
|
+
let c = this.s << bs & this.DM;
|
|
2010
|
+
|
|
2011
|
+
for (let i = this.t - 1; i >= 0; --i) {
|
|
2012
|
+
r[i + ds + 1] = this[i] >> cbs | c;
|
|
2013
|
+
c = (this[i] & bm) << bs;
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
for (let i = ds - 1; i >= 0; --i) {
|
|
2017
|
+
r[i] = 0;
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
r[ds] = c;
|
|
2021
|
+
r.t = this.t + ds + 1;
|
|
2022
|
+
r.s = this.s;
|
|
2023
|
+
r.clamp();
|
|
2024
|
+
} // (protected) r = this >> n
|
|
2025
|
+
|
|
2026
|
+
|
|
2027
|
+
rShiftTo(n, r) {
|
|
2028
|
+
r.s = this.s;
|
|
2029
|
+
const ds = Math.floor(n / this.DB);
|
|
2030
|
+
|
|
2031
|
+
if (ds >= this.t) {
|
|
2032
|
+
r.t = 0;
|
|
2033
|
+
return;
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
const bs = n % this.DB;
|
|
2037
|
+
const cbs = this.DB - bs;
|
|
2038
|
+
const bm = (1 << bs) - 1;
|
|
2039
|
+
r[0] = this[ds] >> bs;
|
|
2040
|
+
|
|
2041
|
+
for (let i = ds + 1; i < this.t; ++i) {
|
|
2042
|
+
r[i - ds - 1] |= (this[i] & bm) << cbs;
|
|
2043
|
+
r[i - ds] = this[i] >> bs;
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
if (bs > 0) {
|
|
2047
|
+
r[this.t - ds - 1] |= (this.s & bm) << cbs;
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
r.t = this.t - ds;
|
|
2051
|
+
r.clamp();
|
|
2052
|
+
} // (protected) r = this - a
|
|
2053
|
+
|
|
2054
|
+
|
|
2055
|
+
subTo(a, r) {
|
|
2056
|
+
let i = 0;
|
|
2057
|
+
let c = 0;
|
|
2058
|
+
const m = Math.min(a.t, this.t);
|
|
2059
|
+
|
|
2060
|
+
while (i < m) {
|
|
2061
|
+
c += this[i] - a[i];
|
|
2062
|
+
r[i++] = c & this.DM;
|
|
2063
|
+
c >>= this.DB;
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2066
|
+
if (a.t < this.t) {
|
|
2067
|
+
c -= a.s;
|
|
2068
|
+
|
|
2069
|
+
while (i < this.t) {
|
|
2070
|
+
c += this[i];
|
|
2071
|
+
r[i++] = c & this.DM;
|
|
2072
|
+
c >>= this.DB;
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
c += this.s;
|
|
2076
|
+
} else {
|
|
2077
|
+
c += this.s;
|
|
2078
|
+
|
|
2079
|
+
while (i < a.t) {
|
|
2080
|
+
c -= a[i];
|
|
2081
|
+
r[i++] = c & this.DM;
|
|
2082
|
+
c >>= this.DB;
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
c -= a.s;
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
r.s = c < 0 ? -1 : 0;
|
|
2089
|
+
|
|
2090
|
+
if (c < -1) {
|
|
2091
|
+
r[i++] = this.DV + c;
|
|
2092
|
+
} else if (c > 0) {
|
|
2093
|
+
r[i++] = c;
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
r.t = i;
|
|
2097
|
+
r.clamp();
|
|
2098
|
+
} // (protected) r = this * a, r != this,a (HAC 14.12)
|
|
2099
|
+
// "this" should be the larger one if appropriate.
|
|
2100
|
+
|
|
2101
|
+
|
|
2102
|
+
multiplyTo(a, r) {
|
|
2103
|
+
const x = this.abs();
|
|
2104
|
+
const y = a.abs();
|
|
2105
|
+
let i = x.t;
|
|
2106
|
+
r.t = i + y.t;
|
|
2107
|
+
|
|
2108
|
+
while (--i >= 0) {
|
|
2109
|
+
r[i] = 0;
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
for (i = 0; i < y.t; ++i) {
|
|
2113
|
+
r[i + x.t] = x.am(0, y[i], r, i, 0, x.t);
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
r.s = 0;
|
|
2117
|
+
r.clamp();
|
|
2118
|
+
|
|
2119
|
+
if (this.s != a.s) {
|
|
2120
|
+
BigInteger.ZERO.subTo(r, r);
|
|
2121
|
+
}
|
|
2122
|
+
} // (protected) r = this^2, r != this (HAC 14.16)
|
|
2123
|
+
|
|
2124
|
+
|
|
2125
|
+
squareTo(r) {
|
|
2126
|
+
const x = this.abs();
|
|
2127
|
+
let i = r.t = 2 * x.t;
|
|
2128
|
+
|
|
2129
|
+
while (--i >= 0) {
|
|
2130
|
+
r[i] = 0;
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
for (i = 0; i < x.t - 1; ++i) {
|
|
2134
|
+
const c = x.am(i, x[i], r, 2 * i, 0, 1);
|
|
2135
|
+
|
|
2136
|
+
if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) {
|
|
2137
|
+
r[i + x.t] -= x.DV;
|
|
2138
|
+
r[i + x.t + 1] = 1;
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
if (r.t > 0) {
|
|
2143
|
+
r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1);
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
r.s = 0;
|
|
2147
|
+
r.clamp();
|
|
2148
|
+
} // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
|
|
2149
|
+
// r != q, this != m. q or r may be null.
|
|
2150
|
+
|
|
2151
|
+
|
|
2152
|
+
divRemTo(m, q, r) {
|
|
2153
|
+
const pm = m.abs();
|
|
2154
|
+
|
|
2155
|
+
if (pm.t <= 0) {
|
|
2156
|
+
return;
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
const pt = this.abs();
|
|
2160
|
+
|
|
2161
|
+
if (pt.t < pm.t) {
|
|
2162
|
+
if (q != null) {
|
|
2163
|
+
q.fromInt(0);
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
if (r != null) {
|
|
2167
|
+
this.copyTo(r);
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
return;
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
if (r == null) {
|
|
2174
|
+
r = nbi();
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
const y = nbi();
|
|
2178
|
+
const ts = this.s;
|
|
2179
|
+
const ms = m.s;
|
|
2180
|
+
const nsh = this.DB - nbits(pm[pm.t - 1]); // normalize modulus
|
|
2181
|
+
|
|
2182
|
+
if (nsh > 0) {
|
|
2183
|
+
pm.lShiftTo(nsh, y);
|
|
2184
|
+
pt.lShiftTo(nsh, r);
|
|
2185
|
+
} else {
|
|
2186
|
+
pm.copyTo(y);
|
|
2187
|
+
pt.copyTo(r);
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
const ys = y.t;
|
|
2191
|
+
const y0 = y[ys - 1];
|
|
2192
|
+
|
|
2193
|
+
if (y0 == 0) {
|
|
2194
|
+
return;
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
const yt = y0 * (1 << this.F1) + (ys > 1 ? y[ys - 2] >> this.F2 : 0);
|
|
2198
|
+
const d1 = this.FV / yt;
|
|
2199
|
+
const d2 = (1 << this.F1) / yt;
|
|
2200
|
+
const e = 1 << this.F2;
|
|
2201
|
+
let i = r.t;
|
|
2202
|
+
let j = i - ys;
|
|
2203
|
+
const t = q == null ? nbi() : q;
|
|
2204
|
+
y.dlShiftTo(j, t);
|
|
2205
|
+
|
|
2206
|
+
if (r.compareTo(t) >= 0) {
|
|
2207
|
+
r[r.t++] = 1;
|
|
2208
|
+
r.subTo(t, r);
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
BigInteger.ONE.dlShiftTo(ys, t);
|
|
2212
|
+
t.subTo(y, y); // "negative" y so we can replace sub with am later
|
|
2213
|
+
|
|
2214
|
+
while (y.t < ys) {
|
|
2215
|
+
y[y.t++] = 0;
|
|
2216
|
+
}
|
|
2217
|
+
|
|
2218
|
+
while (--j >= 0) {
|
|
2219
|
+
// Estimate quotient digit
|
|
2220
|
+
let qd = r[--i] == y0 ? this.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2);
|
|
2221
|
+
|
|
2222
|
+
if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd) {
|
|
2223
|
+
// Try it out
|
|
2224
|
+
y.dlShiftTo(j, t);
|
|
2225
|
+
r.subTo(t, r);
|
|
2226
|
+
|
|
2227
|
+
while (r[i] < --qd) {
|
|
2228
|
+
r.subTo(t, r);
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
if (q != null) {
|
|
2234
|
+
r.drShiftTo(ys, q);
|
|
2235
|
+
|
|
2236
|
+
if (ts != ms) {
|
|
2237
|
+
BigInteger.ZERO.subTo(q, q);
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
r.t = ys;
|
|
2242
|
+
r.clamp();
|
|
2243
|
+
|
|
2244
|
+
if (nsh > 0) {
|
|
2245
|
+
r.rShiftTo(nsh, r);
|
|
2246
|
+
} // Denormalize remainder
|
|
2247
|
+
|
|
2248
|
+
|
|
2249
|
+
if (ts < 0) {
|
|
2250
|
+
BigInteger.ZERO.subTo(r, r);
|
|
2251
|
+
}
|
|
2252
|
+
} // (protected) return "-1/this % 2^DB"; useful for Mont. reduction
|
|
2253
|
+
// justification:
|
|
2254
|
+
// xy == 1 (mod m)
|
|
2255
|
+
// xy = 1+km
|
|
2256
|
+
// xy(2-xy) = (1+km)(1-km)
|
|
2257
|
+
// x[y(2-xy)] = 1-k^2m^2
|
|
2258
|
+
// x[y(2-xy)] == 1 (mod m^2)
|
|
2259
|
+
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
|
|
2260
|
+
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
|
|
2261
|
+
// JS multiply "overflows" differently from C/C++, so care is needed here.
|
|
2262
|
+
|
|
2263
|
+
|
|
2264
|
+
invDigit() {
|
|
2265
|
+
if (this.t < 1) {
|
|
2266
|
+
return 0;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
const x = this[0];
|
|
2270
|
+
|
|
2271
|
+
if ((x & 1) == 0) {
|
|
2272
|
+
return 0;
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
let y = x & 3; // y == 1/x mod 2^2
|
|
2276
|
+
|
|
2277
|
+
y = y * (2 - (x & 0xf) * y) & 0xf; // y == 1/x mod 2^4
|
|
2278
|
+
|
|
2279
|
+
y = y * (2 - (x & 0xff) * y) & 0xff; // y == 1/x mod 2^8
|
|
2280
|
+
|
|
2281
|
+
y = y * (2 - ((x & 0xffff) * y & 0xffff)) & 0xffff; // y == 1/x mod 2^16
|
|
2282
|
+
// last step - calculate inverse mod DV directly;
|
|
2283
|
+
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
|
|
2284
|
+
|
|
2285
|
+
y = y * (2 - x * y % this.DV) % this.DV; // y == 1/x mod 2^dbits
|
|
2286
|
+
// we really want the negative inverse, and -DV < y < DV
|
|
2287
|
+
|
|
2288
|
+
return y > 0 ? this.DV - y : -y;
|
|
2289
|
+
} // (protected) true iff this is even
|
|
2290
|
+
|
|
2291
|
+
|
|
2292
|
+
isEven() {
|
|
2293
|
+
return (this.t > 0 ? this[0] & 1 : this.s) == 0;
|
|
2294
|
+
} // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
|
|
2295
|
+
|
|
2296
|
+
|
|
2297
|
+
exp(e, z) {
|
|
2298
|
+
if (e > 0xffffffff || e < 1) {
|
|
2299
|
+
return BigInteger.ONE;
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
let r = nbi();
|
|
2303
|
+
let r2 = nbi();
|
|
2304
|
+
const g = z.convert(this);
|
|
2305
|
+
let i = nbits(e) - 1;
|
|
2306
|
+
g.copyTo(r);
|
|
2307
|
+
|
|
2308
|
+
while (--i >= 0) {
|
|
2309
|
+
z.sqrTo(r, r2);
|
|
2310
|
+
|
|
2311
|
+
if ((e & 1 << i) > 0) {
|
|
2312
|
+
z.mulTo(r2, g, r);
|
|
2313
|
+
} else {
|
|
2314
|
+
const t = r;
|
|
2315
|
+
r = r2;
|
|
2316
|
+
r2 = t;
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
|
|
2320
|
+
return z.revert(r);
|
|
2321
|
+
} // (protected) return x s.t. r^x < DV
|
|
2322
|
+
|
|
2323
|
+
|
|
2324
|
+
chunkSize(r) {
|
|
2325
|
+
return Math.floor(Math.LN2 * this.DB / Math.log(r));
|
|
2326
|
+
} // (protected) convert to radix string
|
|
2327
|
+
|
|
2328
|
+
|
|
2329
|
+
toRadix(b) {
|
|
2330
|
+
if (b == null) {
|
|
2331
|
+
b = 10;
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2334
|
+
if (this.signum() == 0 || b < 2 || b > 36) {
|
|
2335
|
+
return '0';
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
const cs = this.chunkSize(b);
|
|
2339
|
+
const a = Math.pow(b, cs);
|
|
2340
|
+
const d = nbv(a);
|
|
2341
|
+
const y = nbi();
|
|
2342
|
+
const z = nbi();
|
|
2343
|
+
let r = '';
|
|
2344
|
+
this.divRemTo(d, y, z);
|
|
2345
|
+
|
|
2346
|
+
while (y.signum() > 0) {
|
|
2347
|
+
r = (a + z.intValue()).toString(b).substr(1) + r;
|
|
2348
|
+
y.divRemTo(d, y, z);
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
return z.intValue().toString(b) + r;
|
|
2352
|
+
} // (protected) convert from radix string
|
|
2353
|
+
|
|
2354
|
+
|
|
2355
|
+
fromRadix(s, b) {
|
|
2356
|
+
this.fromInt(0);
|
|
2357
|
+
|
|
2358
|
+
if (b == null) {
|
|
2359
|
+
b = 10;
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
const cs = this.chunkSize(b);
|
|
2363
|
+
const d = Math.pow(b, cs);
|
|
2364
|
+
let mi = false;
|
|
2365
|
+
let j = 0;
|
|
2366
|
+
let w = 0;
|
|
2367
|
+
|
|
2368
|
+
for (let i = 0; i < s.length; ++i) {
|
|
2369
|
+
const x = intAt(s, i);
|
|
2370
|
+
|
|
2371
|
+
if (x < 0) {
|
|
2372
|
+
if (s.charAt(i) == '-' && this.signum() == 0) {
|
|
2373
|
+
mi = true;
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
continue;
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2379
|
+
w = b * w + x;
|
|
2380
|
+
|
|
2381
|
+
if (++j >= cs) {
|
|
2382
|
+
this.dMultiply(d);
|
|
2383
|
+
this.dAddOffset(w, 0);
|
|
2384
|
+
j = 0;
|
|
2385
|
+
w = 0;
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
if (j > 0) {
|
|
2390
|
+
this.dMultiply(Math.pow(b, j));
|
|
2391
|
+
this.dAddOffset(w, 0);
|
|
2392
|
+
}
|
|
2393
|
+
|
|
2394
|
+
if (mi) {
|
|
2395
|
+
BigInteger.ZERO.subTo(this, this);
|
|
2396
|
+
}
|
|
2397
|
+
} // (protected) alternate constructor
|
|
2398
|
+
|
|
2399
|
+
|
|
2400
|
+
fromNumber(a, b, c) {
|
|
2401
|
+
if ('number' == typeof b) {
|
|
2402
|
+
// new BigInteger(int,int,RNG)
|
|
2403
|
+
if (a < 2) {
|
|
2404
|
+
this.fromInt(1);
|
|
2405
|
+
} else {
|
|
2406
|
+
if (typeof c !== 'undefined') {
|
|
2407
|
+
this.fromNumber(a, c);
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
if (!this.testBit(a - 1)) {
|
|
2411
|
+
// force MSB set
|
|
2412
|
+
this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this);
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
if (this.isEven()) {
|
|
2416
|
+
this.dAddOffset(1, 0);
|
|
2417
|
+
} // force odd
|
|
2418
|
+
|
|
2419
|
+
|
|
2420
|
+
while (!this.isProbablePrime(b)) {
|
|
2421
|
+
this.dAddOffset(2, 0);
|
|
2422
|
+
|
|
2423
|
+
if (this.bitLength() > a) {
|
|
2424
|
+
this.subTo(BigInteger.ONE.shiftLeft(a - 1), this);
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
} else {
|
|
2429
|
+
// new BigInteger(int,RNG)
|
|
2430
|
+
const x = [];
|
|
2431
|
+
const t = a & 7;
|
|
2432
|
+
x.length = (a >> 3) + 1;
|
|
2433
|
+
b.nextBytes(x);
|
|
2434
|
+
|
|
2435
|
+
if (t > 0) {
|
|
2436
|
+
x[0] &= (1 << t) - 1;
|
|
2437
|
+
} else {
|
|
2438
|
+
x[0] = 0;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
this.fromString(x, 256);
|
|
2442
|
+
}
|
|
2443
|
+
} // (protected) r = this op a (bitwise)
|
|
2444
|
+
|
|
2445
|
+
|
|
2446
|
+
bitwiseTo(a, op, r) {
|
|
2447
|
+
let i;
|
|
2448
|
+
let f;
|
|
2449
|
+
const m = Math.min(a.t, this.t);
|
|
2450
|
+
|
|
2451
|
+
for (i = 0; i < m; ++i) {
|
|
2452
|
+
r[i] = op(this[i], a[i]);
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
if (a.t < this.t) {
|
|
2456
|
+
f = a.s & this.DM;
|
|
2457
|
+
|
|
2458
|
+
for (i = m; i < this.t; ++i) {
|
|
2459
|
+
r[i] = op(this[i], f);
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
r.t = this.t;
|
|
2463
|
+
} else {
|
|
2464
|
+
f = this.s & this.DM;
|
|
2465
|
+
|
|
2466
|
+
for (i = m; i < a.t; ++i) {
|
|
2467
|
+
r[i] = op(f, a[i]);
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
r.t = a.t;
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
r.s = op(this.s, a.s);
|
|
2474
|
+
r.clamp();
|
|
2475
|
+
} // (protected) this op (1<<n)
|
|
2476
|
+
|
|
2477
|
+
|
|
2478
|
+
changeBit(n, op) {
|
|
2479
|
+
const r = BigInteger.ONE.shiftLeft(n);
|
|
2480
|
+
this.bitwiseTo(r, op, r);
|
|
2481
|
+
return r;
|
|
2482
|
+
} // (protected) r = this + a
|
|
2483
|
+
|
|
2484
|
+
|
|
2485
|
+
addTo(a, r) {
|
|
2486
|
+
let i = 0;
|
|
2487
|
+
let c = 0;
|
|
2488
|
+
const m = Math.min(a.t, this.t);
|
|
2489
|
+
|
|
2490
|
+
while (i < m) {
|
|
2491
|
+
c += this[i] + a[i];
|
|
2492
|
+
r[i++] = c & this.DM;
|
|
2493
|
+
c >>= this.DB;
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
if (a.t < this.t) {
|
|
2497
|
+
c += a.s;
|
|
2498
|
+
|
|
2499
|
+
while (i < this.t) {
|
|
2500
|
+
c += this[i];
|
|
2501
|
+
r[i++] = c & this.DM;
|
|
2502
|
+
c >>= this.DB;
|
|
2503
|
+
}
|
|
2504
|
+
|
|
2505
|
+
c += this.s;
|
|
2506
|
+
} else {
|
|
2507
|
+
c += this.s;
|
|
2508
|
+
|
|
2509
|
+
while (i < a.t) {
|
|
2510
|
+
c += a[i];
|
|
2511
|
+
r[i++] = c & this.DM;
|
|
2512
|
+
c >>= this.DB;
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
c += a.s;
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
r.s = c < 0 ? -1 : 0;
|
|
2519
|
+
|
|
2520
|
+
if (c > 0) {
|
|
2521
|
+
r[i++] = c;
|
|
2522
|
+
} else if (c < -1) {
|
|
2523
|
+
r[i++] = this.DV + c;
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2526
|
+
r.t = i;
|
|
2527
|
+
r.clamp();
|
|
2528
|
+
} // (protected) this *= n, this >= 0, 1 < n < DV
|
|
2529
|
+
|
|
2530
|
+
|
|
2531
|
+
dMultiply(n) {
|
|
2532
|
+
this[this.t] = this.am(0, n - 1, this, 0, 0, this.t);
|
|
2533
|
+
++this.t;
|
|
2534
|
+
this.clamp();
|
|
2535
|
+
} // (protected) this += n << w words, this >= 0
|
|
2536
|
+
|
|
2537
|
+
|
|
2538
|
+
dAddOffset(n, w) {
|
|
2539
|
+
if (n == 0) {
|
|
2540
|
+
return;
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2543
|
+
while (this.t <= w) {
|
|
2544
|
+
this[this.t++] = 0;
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
this[w] += n;
|
|
2548
|
+
|
|
2549
|
+
while (this[w] >= this.DV) {
|
|
2550
|
+
this[w] -= this.DV;
|
|
2551
|
+
|
|
2552
|
+
if (++w >= this.t) {
|
|
2553
|
+
this[this.t++] = 0;
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
++this[w];
|
|
2557
|
+
}
|
|
2558
|
+
} // (protected) r = lower n words of "this * a", a.t <= n
|
|
2559
|
+
// "this" should be the larger one if appropriate.
|
|
2560
|
+
|
|
2561
|
+
|
|
2562
|
+
multiplyLowerTo(a, n, r) {
|
|
2563
|
+
let i = Math.min(this.t + a.t, n);
|
|
2564
|
+
r.s = 0; // assumes a,this >= 0
|
|
2565
|
+
|
|
2566
|
+
r.t = i;
|
|
2567
|
+
|
|
2568
|
+
while (i > 0) {
|
|
2569
|
+
r[--i] = 0;
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
for (const j = r.t - this.t; i < j; ++i) {
|
|
2573
|
+
r[i + this.t] = this.am(0, a[i], r, i, 0, this.t);
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
for (const j = Math.min(a.t, n); i < j; ++i) {
|
|
2577
|
+
this.am(0, a[i], r, i, 0, n - i);
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
r.clamp();
|
|
2581
|
+
} // (protected) r = "this * a" without lower n words, n > 0
|
|
2582
|
+
// "this" should be the larger one if appropriate.
|
|
2583
|
+
|
|
2584
|
+
|
|
2585
|
+
multiplyUpperTo(a, n, r) {
|
|
2586
|
+
--n;
|
|
2587
|
+
let i = r.t = this.t + a.t - n;
|
|
2588
|
+
r.s = 0; // assumes a,this >= 0
|
|
2589
|
+
|
|
2590
|
+
while (--i >= 0) {
|
|
2591
|
+
r[i] = 0;
|
|
2592
|
+
}
|
|
2593
|
+
|
|
2594
|
+
for (i = Math.max(n - this.t, 0); i < a.t; ++i) {
|
|
2595
|
+
r[this.t + i - n] = this.am(n - i, a[i], r, 0, 0, this.t + i - n);
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
r.clamp();
|
|
2599
|
+
r.drShiftTo(1, r);
|
|
2600
|
+
} // (protected) this % n, n < 2^26
|
|
2601
|
+
|
|
2602
|
+
|
|
2603
|
+
modInt(n) {
|
|
2604
|
+
if (n <= 0) {
|
|
2605
|
+
return 0;
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
const d = this.DV % n;
|
|
2609
|
+
let r = this.s < 0 ? n - 1 : 0;
|
|
2610
|
+
|
|
2611
|
+
if (this.t > 0) {
|
|
2612
|
+
if (d == 0) {
|
|
2613
|
+
r = this[0] % n;
|
|
2614
|
+
} else {
|
|
2615
|
+
for (let i = this.t - 1; i >= 0; --i) {
|
|
2616
|
+
r = (d * r + this[i]) % n;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
return r;
|
|
2622
|
+
} // (protected) true if probably prime (HAC 4.24, Miller-Rabin)
|
|
2623
|
+
|
|
2624
|
+
|
|
2625
|
+
millerRabin(t) {
|
|
2626
|
+
const n1 = this.subtract(BigInteger.ONE);
|
|
2627
|
+
const k = n1.getLowestSetBit();
|
|
2628
|
+
|
|
2629
|
+
if (k <= 0) {
|
|
2630
|
+
return false;
|
|
2631
|
+
}
|
|
2632
|
+
|
|
2633
|
+
const r = n1.shiftRight(k);
|
|
2634
|
+
t = t + 1 >> 1;
|
|
2635
|
+
|
|
2636
|
+
if (t > lowprimes.length) {
|
|
2637
|
+
t = lowprimes.length;
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
const a = nbi();
|
|
2641
|
+
|
|
2642
|
+
for (let i = 0; i < t; ++i) {
|
|
2643
|
+
// Pick bases at random, instead of starting at 2
|
|
2644
|
+
a.fromInt(lowprimes[Math.floor(Math.random() * lowprimes.length)]);
|
|
2645
|
+
let y = a.modPow(r, this);
|
|
2646
|
+
|
|
2647
|
+
if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
|
|
2648
|
+
let j = 1;
|
|
2649
|
+
|
|
2650
|
+
while (j++ < k && y.compareTo(n1) != 0) {
|
|
2651
|
+
y = y.modPowInt(2, this);
|
|
2652
|
+
|
|
2653
|
+
if (y.compareTo(BigInteger.ONE) == 0) {
|
|
2654
|
+
return false;
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
|
|
2658
|
+
if (y.compareTo(n1) != 0) {
|
|
2659
|
+
return false;
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2664
|
+
return true;
|
|
2665
|
+
} // (public) this^2
|
|
2666
|
+
|
|
2667
|
+
|
|
2668
|
+
square() {
|
|
2669
|
+
const r = nbi();
|
|
2670
|
+
this.squareTo(r);
|
|
2671
|
+
return r;
|
|
2672
|
+
} //#region ASYNC
|
|
2673
|
+
// Public API method
|
|
2674
|
+
|
|
2675
|
+
|
|
2676
|
+
gcda(a, callback) {
|
|
2677
|
+
let x = this.s < 0 ? this.negate() : this.clone();
|
|
2678
|
+
let y = a.s < 0 ? a.negate() : a.clone();
|
|
2679
|
+
|
|
2680
|
+
if (x.compareTo(y) < 0) {
|
|
2681
|
+
const t = x;
|
|
2682
|
+
x = y;
|
|
2683
|
+
y = t;
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
let i = x.getLowestSetBit();
|
|
2687
|
+
let g = y.getLowestSetBit();
|
|
2688
|
+
|
|
2689
|
+
if (g < 0) {
|
|
2690
|
+
callback(x);
|
|
2691
|
+
return;
|
|
2692
|
+
}
|
|
2693
|
+
|
|
2694
|
+
if (i < g) {
|
|
2695
|
+
g = i;
|
|
2696
|
+
}
|
|
2697
|
+
|
|
2698
|
+
if (g > 0) {
|
|
2699
|
+
x.rShiftTo(g, x);
|
|
2700
|
+
y.rShiftTo(g, y);
|
|
2701
|
+
} // Workhorse of the algorithm, gets called 200 - 800 times per 512 bit keygen.
|
|
2702
|
+
|
|
2703
|
+
|
|
2704
|
+
const gcda1 = function gcda1() {
|
|
2705
|
+
if ((i = x.getLowestSetBit()) > 0) {
|
|
2706
|
+
x.rShiftTo(i, x);
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
if ((i = y.getLowestSetBit()) > 0) {
|
|
2710
|
+
y.rShiftTo(i, y);
|
|
2711
|
+
}
|
|
2712
|
+
|
|
2713
|
+
if (x.compareTo(y) >= 0) {
|
|
2714
|
+
x.subTo(y, x);
|
|
2715
|
+
x.rShiftTo(1, x);
|
|
2716
|
+
} else {
|
|
2717
|
+
y.subTo(x, y);
|
|
2718
|
+
y.rShiftTo(1, y);
|
|
2719
|
+
}
|
|
2720
|
+
|
|
2721
|
+
if (!(x.signum() > 0)) {
|
|
2722
|
+
if (g > 0) {
|
|
2723
|
+
y.lShiftTo(g, y);
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
setTimeout(function () {
|
|
2727
|
+
callback(y);
|
|
2728
|
+
}, 0); // escape
|
|
2729
|
+
} else {
|
|
2730
|
+
setTimeout(gcda1, 0);
|
|
2731
|
+
}
|
|
2732
|
+
};
|
|
2733
|
+
|
|
2734
|
+
setTimeout(gcda1, 10);
|
|
2735
|
+
} // (protected) alternate constructor
|
|
2736
|
+
|
|
2737
|
+
|
|
2738
|
+
fromNumberAsync(a, b, c, callback) {
|
|
2739
|
+
if ('number' == typeof b) {
|
|
2740
|
+
if (a < 2) {
|
|
2741
|
+
this.fromInt(1);
|
|
2742
|
+
} else {
|
|
2743
|
+
this.fromNumber(a, c);
|
|
2744
|
+
|
|
2745
|
+
if (!this.testBit(a - 1)) {
|
|
2746
|
+
this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this);
|
|
2747
|
+
}
|
|
2748
|
+
|
|
2749
|
+
if (this.isEven()) {
|
|
2750
|
+
this.dAddOffset(1, 0);
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
const bnpfn1 = () => {
|
|
2754
|
+
this.dAddOffset(2, 0);
|
|
2755
|
+
|
|
2756
|
+
if (this.bitLength() > a) {
|
|
2757
|
+
this.subTo(BigInteger.ONE.shiftLeft(a - 1), this);
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2760
|
+
if (this.isProbablePrime(b)) {
|
|
2761
|
+
setTimeout(function () {
|
|
2762
|
+
callback();
|
|
2763
|
+
}, 0); // escape
|
|
2764
|
+
} else {
|
|
2765
|
+
setTimeout(bnpfn1, 0);
|
|
2766
|
+
}
|
|
2767
|
+
};
|
|
2768
|
+
|
|
2769
|
+
setTimeout(bnpfn1, 0);
|
|
2770
|
+
}
|
|
2771
|
+
} else {
|
|
2772
|
+
const x = [];
|
|
2773
|
+
const t = a & 7;
|
|
2774
|
+
x.length = (a >> 3) + 1;
|
|
2775
|
+
b.nextBytes(x);
|
|
2776
|
+
|
|
2777
|
+
if (t > 0) {
|
|
2778
|
+
x[0] &= (1 << t) - 1;
|
|
2779
|
+
} else {
|
|
2780
|
+
x[0] = 0;
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
this.fromString(x, 256);
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
am(i, x, w, j, c, n) {
|
|
2788
|
+
if (isIE) {
|
|
2789
|
+
// am2 avoids a big mult-and-extract completely.
|
|
2790
|
+
// Max digit bits should be <= 30 because we do bitwise ops
|
|
2791
|
+
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
|
|
2792
|
+
const xl = x & 0x7fff;
|
|
2793
|
+
const xh = x >> 15;
|
|
2794
|
+
|
|
2795
|
+
while (--n >= 0) {
|
|
2796
|
+
let l = this[i] & 0x7fff;
|
|
2797
|
+
const h = this[i++] >> 15;
|
|
2798
|
+
const m = xh * l + h * xl;
|
|
2799
|
+
l = xl * l + ((m & 0x7fff) << 15) + w[j] + (c & 0x3fffffff);
|
|
2800
|
+
c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30);
|
|
2801
|
+
w[j++] = l & 0x3fffffff;
|
|
2802
|
+
}
|
|
2803
|
+
|
|
2804
|
+
return c;
|
|
2805
|
+
} else if (isNetscapeOrWx) {
|
|
2806
|
+
// am1: use a single mult and divide to get the high bits,
|
|
2807
|
+
// max digit bits should be 26 because
|
|
2808
|
+
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
|
|
2809
|
+
while (--n >= 0) {
|
|
2810
|
+
const v = x * this[i++] + w[j] + c;
|
|
2811
|
+
c = Math.floor(v / 0x4000000);
|
|
2812
|
+
w[j++] = v & 0x3ffffff;
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2815
|
+
return c;
|
|
2816
|
+
} else {
|
|
2817
|
+
// Mozilla/Netscape seems to prefer am3
|
|
2818
|
+
// Alternately, set max digit bits to 28 since some
|
|
2819
|
+
// browsers slow down when dealing with 32-bit numbers.
|
|
2820
|
+
const xl = x & 0x3fff;
|
|
2821
|
+
const xh = x >> 14;
|
|
2822
|
+
|
|
2823
|
+
while (--n >= 0) {
|
|
2824
|
+
let l = this[i] & 0x3fff;
|
|
2825
|
+
const h = this[i++] >> 14;
|
|
2826
|
+
const m = xh * l + h * xl;
|
|
2827
|
+
l = xl * l + ((m & 0x3fff) << 14) + w[j] + c;
|
|
2828
|
+
c = (l >> 28) + (m >> 14) + xh * h;
|
|
2829
|
+
w[j++] = l & 0xfffffff;
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
return c;
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
|
|
2836
|
+
} //#region REDUCERS
|
|
2837
|
+
//#region NullExp
|
|
2838
|
+
|
|
2839
|
+
class NullExp {
|
|
2840
|
+
// NullExp.prototype.convert = nNop;
|
|
2841
|
+
convert(x) {
|
|
2842
|
+
return x;
|
|
2843
|
+
} // NullExp.prototype.revert = nNop;
|
|
2844
|
+
|
|
2845
|
+
|
|
2846
|
+
revert(x) {
|
|
2847
|
+
return x;
|
|
2848
|
+
} // NullExp.prototype.mulTo = nMulTo;
|
|
2849
|
+
|
|
2850
|
+
|
|
2851
|
+
mulTo(x, y, r) {
|
|
2852
|
+
x.multiplyTo(y, r);
|
|
2853
|
+
} // NullExp.prototype.sqrTo = nSqrTo;
|
|
2854
|
+
|
|
2855
|
+
|
|
2856
|
+
sqrTo(x, r) {
|
|
2857
|
+
x.squareTo(r);
|
|
2858
|
+
}
|
|
2859
|
+
|
|
2860
|
+
} // Modular reduction using "classic" algorithm
|
|
2861
|
+
|
|
2862
|
+
|
|
2863
|
+
class Classic {
|
|
2864
|
+
constructor(m) {
|
|
2865
|
+
this.m = m;
|
|
2866
|
+
} // Classic.prototype.convert = cConvert;
|
|
2867
|
+
|
|
2868
|
+
|
|
2869
|
+
convert(x) {
|
|
2870
|
+
if (x.s < 0 || x.compareTo(this.m) >= 0) {
|
|
2871
|
+
return x.mod(this.m);
|
|
2872
|
+
} else {
|
|
2873
|
+
return x;
|
|
2874
|
+
}
|
|
2875
|
+
} // Classic.prototype.revert = cRevert;
|
|
2876
|
+
|
|
2877
|
+
|
|
2878
|
+
revert(x) {
|
|
2879
|
+
return x;
|
|
2880
|
+
} // Classic.prototype.reduce = cReduce;
|
|
2881
|
+
|
|
2882
|
+
|
|
2883
|
+
reduce(x) {
|
|
2884
|
+
x.divRemTo(this.m, null, x);
|
|
2885
|
+
} // Classic.prototype.mulTo = cMulTo;
|
|
2886
|
+
|
|
2887
|
+
|
|
2888
|
+
mulTo(x, y, r) {
|
|
2889
|
+
x.multiplyTo(y, r);
|
|
2890
|
+
this.reduce(r);
|
|
2891
|
+
} // Classic.prototype.sqrTo = cSqrTo;
|
|
2892
|
+
|
|
2893
|
+
|
|
2894
|
+
sqrTo(x, r) {
|
|
2895
|
+
x.squareTo(r);
|
|
2896
|
+
this.reduce(r);
|
|
2897
|
+
}
|
|
2898
|
+
|
|
2899
|
+
} //#endregion
|
|
2900
|
+
//#region Montgomery
|
|
2901
|
+
// Montgomery reduction
|
|
2902
|
+
|
|
2903
|
+
|
|
2904
|
+
class Montgomery {
|
|
2905
|
+
constructor(m) {
|
|
2906
|
+
this.m = m;
|
|
2907
|
+
this.mp = m.invDigit();
|
|
2908
|
+
this.mpl = this.mp & 0x7fff;
|
|
2909
|
+
this.mph = this.mp >> 15;
|
|
2910
|
+
this.um = (1 << m.DB - 15) - 1;
|
|
2911
|
+
this.mt2 = 2 * m.t;
|
|
2912
|
+
} // Montgomery.prototype.convert = montConvert;
|
|
2913
|
+
// xR mod m
|
|
2914
|
+
|
|
2915
|
+
|
|
2916
|
+
convert(x) {
|
|
2917
|
+
const r = nbi();
|
|
2918
|
+
x.abs().dlShiftTo(this.m.t, r);
|
|
2919
|
+
r.divRemTo(this.m, null, r);
|
|
2920
|
+
|
|
2921
|
+
if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) {
|
|
2922
|
+
this.m.subTo(r, r);
|
|
2923
|
+
}
|
|
2924
|
+
|
|
2925
|
+
return r;
|
|
2926
|
+
} // Montgomery.prototype.revert = montRevert;
|
|
2927
|
+
// x/R mod m
|
|
2928
|
+
|
|
2929
|
+
|
|
2930
|
+
revert(x) {
|
|
2931
|
+
const r = nbi();
|
|
2932
|
+
x.copyTo(r);
|
|
2933
|
+
this.reduce(r);
|
|
2934
|
+
return r;
|
|
2935
|
+
} // Montgomery.prototype.reduce = montReduce;
|
|
2936
|
+
// x = x/R mod m (HAC 14.32)
|
|
2937
|
+
|
|
2938
|
+
|
|
2939
|
+
reduce(x) {
|
|
2940
|
+
while (x.t <= this.mt2) {
|
|
2941
|
+
// pad x so am has enough room later
|
|
2942
|
+
x[x.t++] = 0;
|
|
2943
|
+
}
|
|
2944
|
+
|
|
2945
|
+
for (let i = 0; i < this.m.t; ++i) {
|
|
2946
|
+
// faster way of calculating u0 = x[i]*mp mod DV
|
|
2947
|
+
let j = x[i] & 0x7fff;
|
|
2948
|
+
const u0 = j * this.mpl + ((j * this.mph + (x[i] >> 15) * this.mpl & this.um) << 15) & x.DM; // use am to combine the multiply-shift-add into one call
|
|
2949
|
+
|
|
2950
|
+
j = i + this.m.t;
|
|
2951
|
+
x[j] += this.m.am(0, u0, x, i, 0, this.m.t); // propagate carry
|
|
2952
|
+
|
|
2953
|
+
while (x[j] >= x.DV) {
|
|
2954
|
+
x[j] -= x.DV;
|
|
2955
|
+
x[++j]++;
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
|
|
2959
|
+
x.clamp();
|
|
2960
|
+
x.drShiftTo(this.m.t, x);
|
|
2961
|
+
|
|
2962
|
+
if (x.compareTo(this.m) >= 0) {
|
|
2963
|
+
x.subTo(this.m, x);
|
|
2964
|
+
}
|
|
2965
|
+
} // Montgomery.prototype.mulTo = montMulTo;
|
|
2966
|
+
// r = "xy/R mod m"; x,y != r
|
|
2967
|
+
|
|
2968
|
+
|
|
2969
|
+
mulTo(x, y, r) {
|
|
2970
|
+
x.multiplyTo(y, r);
|
|
2971
|
+
this.reduce(r);
|
|
2972
|
+
} // Montgomery.prototype.sqrTo = montSqrTo;
|
|
2973
|
+
// r = "x^2/R mod m"; x != r
|
|
2974
|
+
|
|
2975
|
+
|
|
2976
|
+
sqrTo(x, r) {
|
|
2977
|
+
x.squareTo(r);
|
|
2978
|
+
this.reduce(r);
|
|
2979
|
+
}
|
|
2980
|
+
|
|
2981
|
+
} //#endregion Montgomery
|
|
2982
|
+
//#region Barrett
|
|
2983
|
+
// Barrett modular reduction
|
|
2984
|
+
|
|
2985
|
+
|
|
2986
|
+
class Barrett {
|
|
2987
|
+
constructor(m) {
|
|
2988
|
+
this.m = m; // setup Barrett
|
|
2989
|
+
|
|
2990
|
+
this.r2 = nbi();
|
|
2991
|
+
this.q3 = nbi();
|
|
2992
|
+
BigInteger.ONE.dlShiftTo(2 * m.t, this.r2);
|
|
2993
|
+
this.mu = this.r2.divide(m);
|
|
2994
|
+
} // Barrett.prototype.convert = barrettConvert;
|
|
2995
|
+
|
|
2996
|
+
|
|
2997
|
+
convert(x) {
|
|
2998
|
+
if (x.s < 0 || x.t > 2 * this.m.t) {
|
|
2999
|
+
return x.mod(this.m);
|
|
3000
|
+
} else if (x.compareTo(this.m) < 0) {
|
|
3001
|
+
return x;
|
|
3002
|
+
} else {
|
|
3003
|
+
const r = nbi();
|
|
3004
|
+
x.copyTo(r);
|
|
3005
|
+
this.reduce(r);
|
|
3006
|
+
return r;
|
|
3007
|
+
}
|
|
3008
|
+
} // Barrett.prototype.revert = barrettRevert;
|
|
3009
|
+
|
|
3010
|
+
|
|
3011
|
+
revert(x) {
|
|
3012
|
+
return x;
|
|
3013
|
+
} // Barrett.prototype.reduce = barrettReduce;
|
|
3014
|
+
// x = x mod m (HAC 14.42)
|
|
3015
|
+
|
|
3016
|
+
|
|
3017
|
+
reduce(x) {
|
|
3018
|
+
x.drShiftTo(this.m.t - 1, this.r2);
|
|
3019
|
+
|
|
3020
|
+
if (x.t > this.m.t + 1) {
|
|
3021
|
+
x.t = this.m.t + 1;
|
|
3022
|
+
x.clamp();
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3);
|
|
3026
|
+
this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2);
|
|
3027
|
+
|
|
3028
|
+
while (x.compareTo(this.r2) < 0) {
|
|
3029
|
+
x.dAddOffset(1, this.m.t + 1);
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
x.subTo(this.r2, x);
|
|
3033
|
+
|
|
3034
|
+
while (x.compareTo(this.m) >= 0) {
|
|
3035
|
+
x.subTo(this.m, x);
|
|
3036
|
+
}
|
|
3037
|
+
} // Barrett.prototype.mulTo = barrettMulTo;
|
|
3038
|
+
// r = x*y mod m; x,y != r
|
|
3039
|
+
|
|
3040
|
+
|
|
3041
|
+
mulTo(x, y, r) {
|
|
3042
|
+
x.multiplyTo(y, r);
|
|
3043
|
+
this.reduce(r);
|
|
3044
|
+
} // Barrett.prototype.sqrTo = barrettSqrTo;
|
|
3045
|
+
// r = x^2 mod m; x != r
|
|
3046
|
+
|
|
3047
|
+
|
|
3048
|
+
sqrTo(x, r) {
|
|
3049
|
+
x.squareTo(r);
|
|
3050
|
+
this.reduce(r);
|
|
3051
|
+
}
|
|
3052
|
+
|
|
3053
|
+
} //#endregion
|
|
3054
|
+
//#endregion REDUCERS
|
|
3055
|
+
// return new, unset BigInteger
|
|
3056
|
+
|
|
3057
|
+
|
|
3058
|
+
function nbi() {
|
|
3059
|
+
return new BigInteger(null);
|
|
3060
|
+
}
|
|
3061
|
+
function parseBigInt(str, r) {
|
|
3062
|
+
return new BigInteger(str, r);
|
|
3063
|
+
} // Digit conversions
|
|
3064
|
+
|
|
3065
|
+
const BI_RC = [];
|
|
3066
|
+
let rr;
|
|
3067
|
+
let vv;
|
|
3068
|
+
rr = '0'.charCodeAt(0);
|
|
3069
|
+
|
|
3070
|
+
for (vv = 0; vv <= 9; ++vv) {
|
|
3071
|
+
BI_RC[rr++] = vv;
|
|
3072
|
+
}
|
|
3073
|
+
|
|
3074
|
+
rr = 'a'.charCodeAt(0);
|
|
3075
|
+
|
|
3076
|
+
for (vv = 10; vv < 36; ++vv) {
|
|
3077
|
+
BI_RC[rr++] = vv;
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3080
|
+
rr = 'A'.charCodeAt(0);
|
|
3081
|
+
|
|
3082
|
+
for (vv = 10; vv < 36; ++vv) {
|
|
3083
|
+
BI_RC[rr++] = vv;
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
function intAt(s, i) {
|
|
3087
|
+
const c = BI_RC[s.charCodeAt(i)];
|
|
3088
|
+
return c == null ? -1 : c;
|
|
3089
|
+
} // return bigint initialized to value
|
|
3090
|
+
|
|
3091
|
+
function nbv(i) {
|
|
3092
|
+
const r = nbi();
|
|
3093
|
+
r.fromInt(i);
|
|
3094
|
+
return r;
|
|
3095
|
+
} // returns bit length of the integer x
|
|
3096
|
+
|
|
3097
|
+
function nbits(x) {
|
|
3098
|
+
let r = 1;
|
|
3099
|
+
let t;
|
|
3100
|
+
|
|
3101
|
+
if ((t = x >>> 16) != 0) {
|
|
3102
|
+
x = t;
|
|
3103
|
+
r += 16;
|
|
3104
|
+
}
|
|
3105
|
+
|
|
3106
|
+
if ((t = x >> 8) != 0) {
|
|
3107
|
+
x = t;
|
|
3108
|
+
r += 8;
|
|
3109
|
+
}
|
|
3110
|
+
|
|
3111
|
+
if ((t = x >> 4) != 0) {
|
|
3112
|
+
x = t;
|
|
3113
|
+
r += 4;
|
|
3114
|
+
}
|
|
3115
|
+
|
|
3116
|
+
if ((t = x >> 2) != 0) {
|
|
3117
|
+
x = t;
|
|
3118
|
+
r += 2;
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
if ((t = x >> 1) != 0) {
|
|
3122
|
+
x = t;
|
|
3123
|
+
r += 1;
|
|
3124
|
+
}
|
|
3125
|
+
|
|
3126
|
+
return r;
|
|
3127
|
+
} // "constants"
|
|
3128
|
+
|
|
3129
|
+
BigInteger.ZERO = nbv(0);
|
|
3130
|
+
BigInteger.ONE = nbv(1);
|
|
3131
|
+
|
|
3132
|
+
// prng4.js - uses Arcfour as a PRNG
|
|
3133
|
+
class Arcfour {
|
|
3134
|
+
constructor() {
|
|
3135
|
+
this.i = 0;
|
|
3136
|
+
this.j = 0;
|
|
3137
|
+
this.S = [];
|
|
3138
|
+
} // Arcfour.prototype.init = ARC4init;
|
|
3139
|
+
// Initialize arcfour context from key, an array of ints, each from [0..255]
|
|
3140
|
+
|
|
3141
|
+
|
|
3142
|
+
init(key) {
|
|
3143
|
+
let i;
|
|
3144
|
+
let j;
|
|
3145
|
+
let t;
|
|
3146
|
+
|
|
3147
|
+
for (i = 0; i < 256; ++i) {
|
|
3148
|
+
this.S[i] = i;
|
|
3149
|
+
}
|
|
3150
|
+
|
|
3151
|
+
j = 0;
|
|
3152
|
+
|
|
3153
|
+
for (i = 0; i < 256; ++i) {
|
|
3154
|
+
j = j + this.S[i] + key[i % key.length] & 255;
|
|
3155
|
+
t = this.S[i];
|
|
3156
|
+
this.S[i] = this.S[j];
|
|
3157
|
+
this.S[j] = t;
|
|
3158
|
+
}
|
|
3159
|
+
|
|
3160
|
+
this.i = 0;
|
|
3161
|
+
this.j = 0;
|
|
3162
|
+
} // Arcfour.prototype.next = ARC4next;
|
|
3163
|
+
|
|
3164
|
+
|
|
3165
|
+
next() {
|
|
3166
|
+
this.i = this.i + 1 & 255;
|
|
3167
|
+
this.j = this.j + this.S[this.i] & 255;
|
|
3168
|
+
const t = this.S[this.i];
|
|
3169
|
+
this.S[this.i] = this.S[this.j];
|
|
3170
|
+
this.S[this.j] = t;
|
|
3171
|
+
return this.S[t + this.S[this.i] & 255];
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3174
|
+
} // Plug in your RNG constructor here
|
|
3175
|
+
|
|
3176
|
+
function prng_newstate() {
|
|
3177
|
+
return new Arcfour();
|
|
3178
|
+
} // Pool size must be a multiple of 4 and greater than 32.
|
|
3179
|
+
// An array of bytes the size of the pool will be passed to init()
|
|
3180
|
+
|
|
3181
|
+
const rng_psize = 256;
|
|
3182
|
+
|
|
3183
|
+
// Random number generator - requires a PRNG backend, e.g. prng4.js
|
|
3184
|
+
let rng_state;
|
|
3185
|
+
let rng_pool = [];
|
|
3186
|
+
let rng_pptr; // Initialize the pool with junk if needed.
|
|
3187
|
+
|
|
3188
|
+
if (rng_pool == null) {
|
|
3189
|
+
rng_pool = [];
|
|
3190
|
+
rng_pptr = 0;
|
|
3191
|
+
}
|
|
3192
|
+
|
|
3193
|
+
function rng_get_byte() {
|
|
3194
|
+
if (rng_state == null) {
|
|
3195
|
+
rng_state = prng_newstate(); // At this point, we may not have collected enough entropy. If not, fall back to Math.random
|
|
3196
|
+
|
|
3197
|
+
while (rng_pptr < rng_psize) {
|
|
3198
|
+
const random = Math.floor(65536 * Math.random());
|
|
3199
|
+
rng_pool[rng_pptr++] = random & 255;
|
|
3200
|
+
}
|
|
3201
|
+
|
|
3202
|
+
rng_state.init(rng_pool);
|
|
3203
|
+
|
|
3204
|
+
for (rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) {
|
|
3205
|
+
rng_pool[rng_pptr] = 0;
|
|
3206
|
+
}
|
|
3207
|
+
|
|
3208
|
+
rng_pptr = 0;
|
|
3209
|
+
} // TODO: allow reseeding after first request
|
|
3210
|
+
|
|
3211
|
+
|
|
3212
|
+
return rng_state.next();
|
|
3213
|
+
}
|
|
3214
|
+
|
|
3215
|
+
class SecureRandom {
|
|
3216
|
+
nextBytes(ba) {
|
|
3217
|
+
for (let i = 0; i < ba.length; ++i) {
|
|
3218
|
+
ba[i] = rng_get_byte();
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3221
|
+
|
|
3222
|
+
}
|
|
3223
|
+
|
|
3224
|
+
// Depends on jsbn.js and rng.js
|
|
3225
|
+
|
|
3226
|
+
function pkcs1pad2(s, n) {
|
|
3227
|
+
if (n < s.length + 11) {
|
|
3228
|
+
// TODO: fix for utf-8
|
|
3229
|
+
console.error('Message too long for RSA');
|
|
3230
|
+
return null;
|
|
3231
|
+
}
|
|
3232
|
+
|
|
3233
|
+
const ba = [];
|
|
3234
|
+
let i = s.length - 1;
|
|
3235
|
+
|
|
3236
|
+
while (i >= 0 && n > 0) {
|
|
3237
|
+
const c = s.charCodeAt(i--);
|
|
3238
|
+
|
|
3239
|
+
if (c < 128) {
|
|
3240
|
+
// encode using utf-8
|
|
3241
|
+
ba[--n] = c;
|
|
3242
|
+
} else if (c > 127 && c < 2048) {
|
|
3243
|
+
ba[--n] = c & 63 | 128;
|
|
3244
|
+
ba[--n] = c >> 6 | 192;
|
|
3245
|
+
} else {
|
|
3246
|
+
ba[--n] = c & 63 | 128;
|
|
3247
|
+
ba[--n] = c >> 6 & 63 | 128;
|
|
3248
|
+
ba[--n] = c >> 12 | 224;
|
|
3249
|
+
}
|
|
3250
|
+
}
|
|
3251
|
+
|
|
3252
|
+
ba[--n] = 0;
|
|
3253
|
+
const rng = new SecureRandom();
|
|
3254
|
+
const x = [];
|
|
3255
|
+
|
|
3256
|
+
while (n > 2) {
|
|
3257
|
+
// random non-zero pad
|
|
3258
|
+
x[0] = 0;
|
|
3259
|
+
|
|
3260
|
+
while (x[0] == 0) {
|
|
3261
|
+
rng.nextBytes(x);
|
|
3262
|
+
}
|
|
3263
|
+
|
|
3264
|
+
ba[--n] = x[0];
|
|
3265
|
+
}
|
|
3266
|
+
|
|
3267
|
+
ba[--n] = 2;
|
|
3268
|
+
ba[--n] = 0;
|
|
3269
|
+
return new BigInteger(ba);
|
|
3270
|
+
} // "empty" RSA key constructor
|
|
3271
|
+
|
|
3272
|
+
|
|
3273
|
+
class RSAKey {
|
|
3274
|
+
constructor() {
|
|
3275
|
+
this.e = 0;
|
|
3276
|
+
} //#region PROTECTED
|
|
3277
|
+
// protected
|
|
3278
|
+
// RSAKey.prototype.doPublic = RSADoPublic;
|
|
3279
|
+
// Perform raw public operation on "x": return x^e (mod n)
|
|
3280
|
+
|
|
3281
|
+
|
|
3282
|
+
doPublic(x) {
|
|
3283
|
+
if (this.n) {
|
|
3284
|
+
return x.modPowInt(this.e, this.n);
|
|
3285
|
+
}
|
|
3286
|
+
|
|
3287
|
+
return null;
|
|
3288
|
+
} //#endregion PROTECTED
|
|
3289
|
+
//#region PUBLIC
|
|
3290
|
+
// RSAKey.prototype.setPublic = RSASetPublic;
|
|
3291
|
+
// Set the public key fields N and e from hex strings
|
|
3292
|
+
|
|
3293
|
+
|
|
3294
|
+
setPublic(N, E) {
|
|
3295
|
+
if (N != null && E != null && N.length > 0 && E.length > 0) {
|
|
3296
|
+
this.n = parseBigInt(N, 16);
|
|
3297
|
+
this.e = parseInt(E, 16);
|
|
3298
|
+
} else {
|
|
3299
|
+
console.error('Invalid RSA public key');
|
|
3300
|
+
}
|
|
3301
|
+
} // RSAKey.prototype.encrypt = RSAEncrypt;
|
|
3302
|
+
// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
|
|
3303
|
+
|
|
3304
|
+
|
|
3305
|
+
encrypt(text) {
|
|
3306
|
+
if (!this.n) {
|
|
3307
|
+
return null;
|
|
3308
|
+
}
|
|
3309
|
+
|
|
3310
|
+
const maxLength = this.n.bitLength() + 7 >> 3;
|
|
3311
|
+
const m = pkcs1pad2(text, maxLength);
|
|
3312
|
+
|
|
3313
|
+
if (m == null) {
|
|
3314
|
+
return null;
|
|
3315
|
+
}
|
|
3316
|
+
|
|
3317
|
+
const c = this.doPublic(m);
|
|
3318
|
+
|
|
3319
|
+
if (c == null) {
|
|
3320
|
+
return null;
|
|
3321
|
+
}
|
|
3322
|
+
|
|
3323
|
+
let h = c.toString(16);
|
|
3324
|
+
const length = h.length; // fix zero before result
|
|
3325
|
+
|
|
3326
|
+
for (let i = 0; i < maxLength * 2 - length; i++) {
|
|
3327
|
+
h = '0' + h;
|
|
3328
|
+
}
|
|
3329
|
+
|
|
3330
|
+
return h;
|
|
3331
|
+
} // RSAKey.prototype.generate = RSAGenerate;
|
|
3332
|
+
// Generate a new random private key B bits long, using public expt E
|
|
3333
|
+
|
|
3334
|
+
|
|
3335
|
+
generate(B, E) {
|
|
3336
|
+
const rng = new SecureRandom();
|
|
3337
|
+
const qs = B >> 1;
|
|
3338
|
+
this.e = parseInt(E, 16);
|
|
3339
|
+
const ee = new BigInteger(E, 16);
|
|
3340
|
+
|
|
3341
|
+
for (;;) {
|
|
3342
|
+
for (;;) {
|
|
3343
|
+
this.p = new BigInteger(B - qs, 1, rng);
|
|
3344
|
+
|
|
3345
|
+
if (this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) {
|
|
3346
|
+
break;
|
|
3347
|
+
}
|
|
3348
|
+
}
|
|
3349
|
+
|
|
3350
|
+
for (;;) {
|
|
3351
|
+
this.q = new BigInteger(qs, 1, rng);
|
|
3352
|
+
|
|
3353
|
+
if (this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) {
|
|
3354
|
+
break;
|
|
3355
|
+
}
|
|
3356
|
+
}
|
|
3357
|
+
|
|
3358
|
+
if (this.p.compareTo(this.q) <= 0) {
|
|
3359
|
+
const t = this.p;
|
|
3360
|
+
this.p = this.q;
|
|
3361
|
+
this.q = t;
|
|
3362
|
+
}
|
|
3363
|
+
|
|
3364
|
+
const p1 = this.p.subtract(BigInteger.ONE);
|
|
3365
|
+
const q1 = this.q.subtract(BigInteger.ONE);
|
|
3366
|
+
const phi = p1.multiply(q1);
|
|
3367
|
+
|
|
3368
|
+
if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
|
|
3369
|
+
this.n = this.p.multiply(this.q);
|
|
3370
|
+
this.d = ee.modInverse(phi);
|
|
3371
|
+
this.dmp1 = this.d.mod(p1);
|
|
3372
|
+
this.dmq1 = this.d.mod(q1);
|
|
3373
|
+
this.coeff = this.q.modInverse(this.p);
|
|
3374
|
+
break;
|
|
3375
|
+
}
|
|
3376
|
+
}
|
|
3377
|
+
} // Generate a new random private key B bits long, using public expt E
|
|
3378
|
+
|
|
3379
|
+
|
|
3380
|
+
generateAsync(B, E, callback) {
|
|
3381
|
+
const rng = new SecureRandom();
|
|
3382
|
+
const qs = B >> 1;
|
|
3383
|
+
this.e = parseInt(E, 16);
|
|
3384
|
+
const ee = new BigInteger(E, 16); // These functions have non-descript names because they were originally for(;;) loops.
|
|
3385
|
+
// I don't know about cryptography to give them better names than loop1-4.
|
|
3386
|
+
|
|
3387
|
+
const loop1 = () => {
|
|
3388
|
+
const loop4 = () => {
|
|
3389
|
+
if (this.p.compareTo(this.q) <= 0) {
|
|
3390
|
+
const t = this.p;
|
|
3391
|
+
this.p = this.q;
|
|
3392
|
+
this.q = t;
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
const p1 = this.p.subtract(BigInteger.ONE);
|
|
3396
|
+
const q1 = this.q.subtract(BigInteger.ONE);
|
|
3397
|
+
const phi = p1.multiply(q1);
|
|
3398
|
+
|
|
3399
|
+
if (phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
|
|
3400
|
+
this.n = this.p.multiply(this.q);
|
|
3401
|
+
this.d = ee.modInverse(phi);
|
|
3402
|
+
this.dmp1 = this.d.mod(p1);
|
|
3403
|
+
this.dmq1 = this.d.mod(q1);
|
|
3404
|
+
this.coeff = this.q.modInverse(this.p);
|
|
3405
|
+
setTimeout(function () {
|
|
3406
|
+
callback();
|
|
3407
|
+
}, 0); // escape
|
|
3408
|
+
} else {
|
|
3409
|
+
setTimeout(loop1, 0);
|
|
3410
|
+
}
|
|
3411
|
+
};
|
|
3412
|
+
|
|
3413
|
+
const loop3 = () => {
|
|
3414
|
+
this.q = nbi();
|
|
3415
|
+
this.q.fromNumberAsync(qs, 1, rng, () => {
|
|
3416
|
+
this.q.subtract(BigInteger.ONE).gcda(ee, r => {
|
|
3417
|
+
if (r.compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) {
|
|
3418
|
+
setTimeout(loop4, 0);
|
|
3419
|
+
} else {
|
|
3420
|
+
setTimeout(loop3, 0);
|
|
3421
|
+
}
|
|
3422
|
+
});
|
|
3423
|
+
});
|
|
3424
|
+
};
|
|
3425
|
+
|
|
3426
|
+
const loop2 = () => {
|
|
3427
|
+
this.p = nbi();
|
|
3428
|
+
this.p.fromNumberAsync(B - qs, 1, rng, () => {
|
|
3429
|
+
this.p.subtract(BigInteger.ONE).gcda(ee, r => {
|
|
3430
|
+
if (r.compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) {
|
|
3431
|
+
setTimeout(loop3, 0);
|
|
3432
|
+
} else {
|
|
3433
|
+
setTimeout(loop2, 0);
|
|
3434
|
+
}
|
|
3435
|
+
});
|
|
3436
|
+
});
|
|
3437
|
+
};
|
|
3438
|
+
|
|
3439
|
+
setTimeout(loop2, 0);
|
|
3440
|
+
};
|
|
3441
|
+
|
|
3442
|
+
setTimeout(loop1, 0);
|
|
3443
|
+
}
|
|
3444
|
+
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3447
|
+
/**
|
|
3448
|
+
* Create a new JSEncryptRSAKey that extends Tom Wu's RSA key object.
|
|
3449
|
+
* This object is just a decorator for parsing the key parameter
|
|
3450
|
+
* @param {string|Object} key - The key in string format, or an object containing
|
|
3451
|
+
* the parameters needed to build a RSAKey object.
|
|
3452
|
+
* @constructor
|
|
3453
|
+
*/
|
|
3454
|
+
|
|
3455
|
+
class JSEncryptRSAKey extends RSAKey {
|
|
3456
|
+
constructor(key) {
|
|
3457
|
+
super(); // Call the super constructor.
|
|
3458
|
+
// RSAKey.call(this);
|
|
3459
|
+
// If a key key was provided.
|
|
3460
|
+
|
|
3461
|
+
if (key) {
|
|
3462
|
+
// If this is a string...
|
|
3463
|
+
if (typeof key === 'string') {
|
|
3464
|
+
this.parseKey(key);
|
|
3465
|
+
} else if (JSEncryptRSAKey.hasPublicKeyProperty(key)) {
|
|
3466
|
+
// Set the values for the key.
|
|
3467
|
+
this.parsePropertiesFrom(key);
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
/**
|
|
3472
|
+
* Method to parse a pem encoded string containing both a public or private key.
|
|
3473
|
+
* The method will translate the pem encoded string in a der encoded string and
|
|
3474
|
+
* will parse private key and public key parameters. This method accepts public key
|
|
3475
|
+
* in the rsaencryption pkcs #1 format (oid: 1.2.840.113549.1.1.1).
|
|
3476
|
+
*
|
|
3477
|
+
* @todo Check how many rsa formats use the same format of pkcs #1.
|
|
3478
|
+
*
|
|
3479
|
+
* The format is defined as:
|
|
3480
|
+
* PublicKeyInfo ::= SEQUENCE {
|
|
3481
|
+
* algorithm AlgorithmIdentifier,
|
|
3482
|
+
* PublicKey BIT STRING
|
|
3483
|
+
* }
|
|
3484
|
+
* Where AlgorithmIdentifier is:
|
|
3485
|
+
* AlgorithmIdentifier ::= SEQUENCE {
|
|
3486
|
+
* algorithm OBJECT IDENTIFIER, the OID of the enc algorithm
|
|
3487
|
+
* parameters ANY DEFINED BY algorithm OPTIONAL (NULL for PKCS #1)
|
|
3488
|
+
* }
|
|
3489
|
+
* and PublicKey is a SEQUENCE encapsulated in a BIT STRING
|
|
3490
|
+
* RSAPublicKey ::= SEQUENCE {
|
|
3491
|
+
* modulus INTEGER, -- n
|
|
3492
|
+
* publicExponent INTEGER -- e
|
|
3493
|
+
* }
|
|
3494
|
+
* it's possible to examine the structure of the keys obtained from openssl using
|
|
3495
|
+
* an asn.1 dumper as the one used here to parse the components: http://lapo.it/asn1js/
|
|
3496
|
+
* @argument {string} pem the pem encoded string, can include the BEGIN/END header/footer
|
|
3497
|
+
* @private
|
|
3498
|
+
*/
|
|
3499
|
+
|
|
3500
|
+
|
|
3501
|
+
parseKey(pem) {
|
|
3502
|
+
try {
|
|
3503
|
+
let modulus = 0;
|
|
3504
|
+
let public_exponent = 0;
|
|
3505
|
+
const reHex = /^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/;
|
|
3506
|
+
const der = reHex.test(pem) ? Hex.decode(pem) : Base64.unarmor(pem);
|
|
3507
|
+
let asn1 = ASN1.decode(der); // Fixes a bug with OpenSSL 1.0+ private keys
|
|
3508
|
+
|
|
3509
|
+
if (asn1.sub && asn1.sub.length === 3) {
|
|
3510
|
+
if (asn1.sub[2].sub) {
|
|
3511
|
+
asn1 = asn1.sub[2].sub[0];
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
|
|
3515
|
+
if (asn1.sub && asn1.sub.length === 9) {
|
|
3516
|
+
// Parse the private key.
|
|
3517
|
+
modulus = asn1.sub[1].getHexStringValue(); // bigint
|
|
3518
|
+
|
|
3519
|
+
this.n = parseBigInt(modulus, 16);
|
|
3520
|
+
public_exponent = asn1.sub[2].getHexStringValue(); // int
|
|
3521
|
+
|
|
3522
|
+
this.e = parseInt(public_exponent, 16);
|
|
3523
|
+
const private_exponent = asn1.sub[3].getHexStringValue(); // bigint
|
|
3524
|
+
|
|
3525
|
+
this.d = parseBigInt(private_exponent, 16);
|
|
3526
|
+
const prime1 = asn1.sub[4].getHexStringValue(); // bigint
|
|
3527
|
+
|
|
3528
|
+
this.p = parseBigInt(prime1, 16);
|
|
3529
|
+
const prime2 = asn1.sub[5].getHexStringValue(); // bigint
|
|
3530
|
+
|
|
3531
|
+
this.q = parseBigInt(prime2, 16);
|
|
3532
|
+
const exponent1 = asn1.sub[6].getHexStringValue(); // bigint
|
|
3533
|
+
|
|
3534
|
+
this.dmp1 = parseBigInt(exponent1, 16);
|
|
3535
|
+
const exponent2 = asn1.sub[7].getHexStringValue(); // bigint
|
|
3536
|
+
|
|
3537
|
+
this.dmq1 = parseBigInt(exponent2, 16);
|
|
3538
|
+
const coefficient = asn1.sub[8].getHexStringValue(); // bigint
|
|
3539
|
+
|
|
3540
|
+
this.coeff = parseBigInt(coefficient, 16);
|
|
3541
|
+
} else if (asn1.sub && asn1.sub.length === 2) {
|
|
3542
|
+
// Parse the public key.
|
|
3543
|
+
const bit_string = asn1.sub[1];
|
|
3544
|
+
|
|
3545
|
+
if (bit_string.sub) {
|
|
3546
|
+
const sequence = bit_string.sub[0];
|
|
3547
|
+
|
|
3548
|
+
if (sequence.sub) {
|
|
3549
|
+
modulus = sequence.sub[0].getHexStringValue();
|
|
3550
|
+
this.n = parseBigInt(modulus, 16);
|
|
3551
|
+
public_exponent = sequence.sub[1].getHexStringValue();
|
|
3552
|
+
this.e = parseInt(public_exponent, 16);
|
|
3553
|
+
} else {
|
|
3554
|
+
return false;
|
|
3555
|
+
}
|
|
3556
|
+
} else {
|
|
3557
|
+
return false;
|
|
3558
|
+
}
|
|
3559
|
+
} else {
|
|
3560
|
+
return false;
|
|
3561
|
+
}
|
|
3562
|
+
|
|
3563
|
+
return true;
|
|
3564
|
+
} catch (ex) {
|
|
3565
|
+
return false;
|
|
3566
|
+
}
|
|
3567
|
+
}
|
|
3568
|
+
/**
|
|
3569
|
+
* Check if the object contains the necessary parameters to populate the rsa modulus
|
|
3570
|
+
* and public exponent parameters.
|
|
3571
|
+
* @param {Object} [obj={}] - An object that may contain the two public key
|
|
3572
|
+
* parameters
|
|
3573
|
+
* @returns {boolean} true if the object contains both the modulus and the public exponent
|
|
3574
|
+
* properties (n and e)
|
|
3575
|
+
* @todo check for types of n and e. N should be a parseable bigInt object, E should
|
|
3576
|
+
* be a parseable integer number
|
|
3577
|
+
* @private
|
|
3578
|
+
*/
|
|
3579
|
+
|
|
3580
|
+
|
|
3581
|
+
static hasPublicKeyProperty(obj) {
|
|
3582
|
+
obj = obj || {}; // eslint-disable-next-line no-prototype-builtins
|
|
3583
|
+
|
|
3584
|
+
return obj.hasOwnProperty('n') && obj.hasOwnProperty('e');
|
|
3585
|
+
}
|
|
3586
|
+
/**
|
|
3587
|
+
* Parse the properties of obj in the current rsa object. Obj should AT LEAST
|
|
3588
|
+
* include the modulus and public exponent (n, e) parameters.
|
|
3589
|
+
* @param {Object} obj - the object containing rsa parameters
|
|
3590
|
+
* @private
|
|
3591
|
+
*/
|
|
3592
|
+
|
|
3593
|
+
|
|
3594
|
+
parsePropertiesFrom(obj) {
|
|
3595
|
+
this.n = obj.n;
|
|
3596
|
+
this.e = obj.e; // eslint-disable-next-line no-prototype-builtins
|
|
3597
|
+
|
|
3598
|
+
if (obj.hasOwnProperty('d')) {
|
|
3599
|
+
this.d = obj.d;
|
|
3600
|
+
this.p = obj.p;
|
|
3601
|
+
this.q = obj.q;
|
|
3602
|
+
this.dmp1 = obj.dmp1;
|
|
3603
|
+
this.dmq1 = obj.dmq1;
|
|
3604
|
+
this.coeff = obj.coeff;
|
|
3605
|
+
}
|
|
3606
|
+
}
|
|
3607
|
+
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3610
|
+
/**
|
|
3611
|
+
*
|
|
3612
|
+
* @param {Object} [options = {}] - An object to customize JSEncrypt behaviour
|
|
3613
|
+
* possible parameters are:
|
|
3614
|
+
* - default_key_size {number} default: 1024 the key size in bit
|
|
3615
|
+
* - default_public_exponent {string} default: '010001' the hexadecimal representation of the public exponent
|
|
3616
|
+
* - log {boolean} default: false whether log warn/error or not
|
|
3617
|
+
* @constructor
|
|
3618
|
+
*/
|
|
3619
|
+
|
|
3620
|
+
class JSEncrypt {
|
|
3621
|
+
constructor(options = {}) {
|
|
3622
|
+
options = options || {};
|
|
3623
|
+
this.default_key_size = options.default_key_size ? parseInt(options.default_key_size, 10) : 1024;
|
|
3624
|
+
this.default_public_exponent = options.default_public_exponent || '010001'; // 65537 default openssl public exponent for rsa key type
|
|
3625
|
+
|
|
3626
|
+
this.log = options.log || false;
|
|
3627
|
+
}
|
|
3628
|
+
/**
|
|
3629
|
+
* Method to set the rsa key parameter (one method is enough to set both the public
|
|
3630
|
+
* and the private key, since the private key contains the public key paramenters)
|
|
3631
|
+
* Log a warning if logs are enabled
|
|
3632
|
+
* @param {Object|string} key the pem encoded string or an object (with or without header/footer)
|
|
3633
|
+
* @public
|
|
3634
|
+
*/
|
|
3635
|
+
|
|
3636
|
+
|
|
3637
|
+
setKey(key) {
|
|
3638
|
+
if (this.log && this.key) {
|
|
3639
|
+
console.warn('A key was already set, overriding existing.');
|
|
3640
|
+
}
|
|
3641
|
+
|
|
3642
|
+
this.key = new JSEncryptRSAKey(key);
|
|
3643
|
+
}
|
|
3644
|
+
/**
|
|
3645
|
+
* Proxy method for setKey, for api compatibility
|
|
3646
|
+
* @see setKey
|
|
3647
|
+
* @public
|
|
3648
|
+
*/
|
|
3649
|
+
|
|
3650
|
+
|
|
3651
|
+
setPublicKey(pubkey) {
|
|
3652
|
+
// Sets the public key.
|
|
3653
|
+
this.setKey(pubkey);
|
|
3654
|
+
}
|
|
3655
|
+
/**
|
|
3656
|
+
* Proxy method for RSAKey object's encrypt, encrypt the string using the public
|
|
3657
|
+
* components of the rsa key object. Note that if the object was not set will be created
|
|
3658
|
+
* on the fly (by the getKey method) using the parameters passed in the JSEncrypt constructor
|
|
3659
|
+
* @param {string} str the string to encrypt
|
|
3660
|
+
* @return {string} the encrypted string encoded in base64
|
|
3661
|
+
* @public
|
|
3662
|
+
*/
|
|
3663
|
+
|
|
3664
|
+
|
|
3665
|
+
encrypt(str) {
|
|
3666
|
+
// Return the encrypted string.
|
|
3667
|
+
try {
|
|
3668
|
+
const text = this.getKey().encrypt(str);
|
|
3669
|
+
|
|
3670
|
+
if (typeof text === 'string') {
|
|
3671
|
+
return hex2b64(text);
|
|
3672
|
+
}
|
|
3673
|
+
} catch (ex) {//
|
|
3674
|
+
}
|
|
3675
|
+
|
|
3676
|
+
return '';
|
|
3677
|
+
}
|
|
3678
|
+
/**
|
|
3679
|
+
* Getter for the current JSEncryptRSAKey object. If it doesn't exists a new object
|
|
3680
|
+
* will be created and returned
|
|
3681
|
+
* @param {callback} [cb] the callback to be called if we want the key to be generated
|
|
3682
|
+
* in an async fashion
|
|
3683
|
+
* @returns {JSEncryptRSAKey} the JSEncryptRSAKey object
|
|
3684
|
+
* @public
|
|
3685
|
+
*/
|
|
3686
|
+
|
|
3687
|
+
|
|
3688
|
+
getKey(cb) {
|
|
3689
|
+
// Only create new if it does not exist.
|
|
3690
|
+
if (!this.key) {
|
|
3691
|
+
// Get a new private key.
|
|
3692
|
+
this.key = new JSEncryptRSAKey();
|
|
3693
|
+
|
|
3694
|
+
if (cb && {}.toString.call(cb) === '[object Function]') {
|
|
3695
|
+
this.key.generateAsync(this.default_key_size, this.default_public_exponent, cb);
|
|
3696
|
+
return this.key;
|
|
3697
|
+
} // Generate the key.
|
|
3698
|
+
|
|
3699
|
+
|
|
3700
|
+
this.key.generate(this.default_key_size, this.default_public_exponent);
|
|
3701
|
+
}
|
|
3702
|
+
|
|
3703
|
+
return this.key;
|
|
3704
|
+
}
|
|
3705
|
+
|
|
3706
|
+
}
|
|
3707
|
+
|
|
3708
|
+
exports.JSEncrypt = JSEncrypt;
|
|
3709
|
+
exports["default"] = JSEncrypt;
|