@ray-js/wechat-tycrypto 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 +1751 -0
- package/index.esm.js +1740 -0
- package/package.json +23 -0
- package/src/index.d.ts +6 -0
- package/src/lib/aes/aes.asm.d.ts +113 -0
- package/src/lib/aes/aes.d.ts +15 -0
- package/src/lib/aes/cbc.d.ts +9 -0
- package/src/lib/aes/ccm.d.ts +36 -0
- package/src/lib/aes/ecb.d.ts +10 -0
- package/src/lib/aes/exports.d.ts +3 -0
- package/src/lib/aes/gcm.d.ts +21 -0
- package/src/lib/other/errors.d.ts +9 -0
- package/src/lib/other/utils.d.ts +9 -0
package/index..js
ADDED
|
@@ -0,0 +1,1751 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
class IllegalStateError extends Error {
|
|
6
|
+
constructor(...args) {
|
|
7
|
+
super(...args);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
}
|
|
11
|
+
class IllegalArgumentError extends Error {
|
|
12
|
+
constructor(...args) {
|
|
13
|
+
super(...args);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
class SecurityError extends Error {
|
|
18
|
+
constructor(...args) {
|
|
19
|
+
super(...args);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function is_bytes(a) {
|
|
25
|
+
return a instanceof Uint8Array;
|
|
26
|
+
}
|
|
27
|
+
function _heap_init(heap, heapSize) {
|
|
28
|
+
const size = heap ? heap.byteLength : heapSize || 65536;
|
|
29
|
+
if (size & 0xfff || size <= 0) throw new Error('heap size must be a positive integer and a multiple of 4096');
|
|
30
|
+
heap = heap || new Uint8Array(new ArrayBuffer(size));
|
|
31
|
+
return heap;
|
|
32
|
+
}
|
|
33
|
+
function _heap_write(heap, hpos, data, dpos, dlen) {
|
|
34
|
+
const hlen = heap.length - hpos;
|
|
35
|
+
const wlen = hlen < dlen ? hlen : dlen;
|
|
36
|
+
heap.set(data.subarray(dpos, dpos + wlen), hpos);
|
|
37
|
+
return wlen;
|
|
38
|
+
}
|
|
39
|
+
function joinBytes(...arg) {
|
|
40
|
+
const totalLenght = arg.reduce((sum, curr) => sum + curr.length, 0);
|
|
41
|
+
const ret = new Uint8Array(totalLenght);
|
|
42
|
+
let cursor = 0;
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < arg.length; i++) {
|
|
45
|
+
ret.set(arg[i], cursor);
|
|
46
|
+
cursor += arg[i].length;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return ret;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}.
|
|
54
|
+
* @author Artem S Vybornov <vybornov@gmail.com>
|
|
55
|
+
* @license MIT
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Galois Field stuff init flag
|
|
60
|
+
*/
|
|
61
|
+
let ginit_done = false;
|
|
62
|
+
/**
|
|
63
|
+
* Galois Field exponentiation and logarithm tables for 3 (the generator)
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
let gexp3;
|
|
67
|
+
let glog3;
|
|
68
|
+
/**
|
|
69
|
+
* Init Galois Field tables
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
function ginit() {
|
|
73
|
+
gexp3 = [];
|
|
74
|
+
glog3 = [];
|
|
75
|
+
let a = 1,
|
|
76
|
+
c,
|
|
77
|
+
d;
|
|
78
|
+
|
|
79
|
+
for (c = 0; c < 255; c++) {
|
|
80
|
+
gexp3[c] = a; // Multiply by three
|
|
81
|
+
|
|
82
|
+
d = a & 0x80, a <<= 1, a &= 255;
|
|
83
|
+
if (d === 0x80) a ^= 0x1b;
|
|
84
|
+
a ^= gexp3[c]; // Set the log table value
|
|
85
|
+
|
|
86
|
+
glog3[gexp3[c]] = c;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
gexp3[255] = gexp3[0];
|
|
90
|
+
glog3[0] = 0;
|
|
91
|
+
ginit_done = true;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Galois Field multiplication
|
|
95
|
+
* @param {number} a
|
|
96
|
+
* @param {number} b
|
|
97
|
+
* @return {number}
|
|
98
|
+
*/
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
function gmul(a, b) {
|
|
102
|
+
let c = gexp3[(glog3[a] + glog3[b]) % 255];
|
|
103
|
+
if (a === 0 || b === 0) c = 0;
|
|
104
|
+
return c;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Galois Field reciprocal
|
|
108
|
+
* @param {number} a
|
|
109
|
+
* @return {number}
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
function ginv(a) {
|
|
114
|
+
let i = gexp3[255 - glog3[a]];
|
|
115
|
+
if (a === 0) i = 0;
|
|
116
|
+
return i;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* AES stuff init flag
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
let aes_init_done = false;
|
|
124
|
+
/**
|
|
125
|
+
* Encryption, Decryption, S-Box and KeyTransform tables
|
|
126
|
+
*
|
|
127
|
+
* @type {number[]}
|
|
128
|
+
*/
|
|
129
|
+
|
|
130
|
+
let aes_sbox;
|
|
131
|
+
/**
|
|
132
|
+
* @type {number[]}
|
|
133
|
+
*/
|
|
134
|
+
|
|
135
|
+
let aes_sinv;
|
|
136
|
+
/**
|
|
137
|
+
* @type {number[][]}
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
let aes_enc;
|
|
141
|
+
/**
|
|
142
|
+
* @type {number[][]}
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
let aes_dec;
|
|
146
|
+
/**
|
|
147
|
+
* Init AES tables
|
|
148
|
+
*/
|
|
149
|
+
|
|
150
|
+
function aes_init() {
|
|
151
|
+
if (!ginit_done) ginit(); // Calculates AES S-Box value
|
|
152
|
+
|
|
153
|
+
function _s(a) {
|
|
154
|
+
let c, s, x;
|
|
155
|
+
s = x = ginv(a);
|
|
156
|
+
|
|
157
|
+
for (c = 0; c < 4; c++) {
|
|
158
|
+
s = (s << 1 | s >>> 7) & 255;
|
|
159
|
+
x ^= s;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
x ^= 99;
|
|
163
|
+
return x;
|
|
164
|
+
} // Tables
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
aes_sbox = [], aes_sinv = [], aes_enc = [[], [], [], []], aes_dec = [[], [], [], []];
|
|
168
|
+
|
|
169
|
+
for (let i = 0; i < 256; i++) {
|
|
170
|
+
const s = _s(i); // S-Box and its inverse
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
aes_sbox[i] = s;
|
|
174
|
+
aes_sinv[s] = i; // Ecryption and Decryption tables
|
|
175
|
+
|
|
176
|
+
aes_enc[0][i] = gmul(2, s) << 24 | s << 16 | s << 8 | gmul(3, s);
|
|
177
|
+
aes_dec[0][s] = gmul(14, i) << 24 | gmul(9, i) << 16 | gmul(13, i) << 8 | gmul(11, i); // Rotate tables
|
|
178
|
+
|
|
179
|
+
for (let t = 1; t < 4; t++) {
|
|
180
|
+
aes_enc[t][i] = aes_enc[t - 1][i] >>> 8 | aes_enc[t - 1][i] << 24;
|
|
181
|
+
aes_dec[t][s] = aes_dec[t - 1][s] >>> 8 | aes_dec[t - 1][s] << 24;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
aes_init_done = true;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Asm.js module constructor.
|
|
189
|
+
*
|
|
190
|
+
* <p>
|
|
191
|
+
* Heap buffer layout by offset:
|
|
192
|
+
* <pre>
|
|
193
|
+
* 0x0000 encryption key schedule
|
|
194
|
+
* 0x0400 decryption key schedule
|
|
195
|
+
* 0x0800 sbox
|
|
196
|
+
* 0x0c00 inv sbox
|
|
197
|
+
* 0x1000 encryption tables
|
|
198
|
+
* 0x2000 decryption tables
|
|
199
|
+
* 0x3000 reserved (future GCM multiplication lookup table)
|
|
200
|
+
* 0x4000 data
|
|
201
|
+
* </pre>
|
|
202
|
+
* Don't touch anything before <code>0x400</code>.
|
|
203
|
+
* </p>
|
|
204
|
+
*
|
|
205
|
+
* @alias AES_asm
|
|
206
|
+
* @class
|
|
207
|
+
* @param foreign - <i>ignored</i>
|
|
208
|
+
* @param buffer - heap buffer to link with
|
|
209
|
+
*/
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
const wrapper = function wrapper(foreign, buffer) {
|
|
213
|
+
// Init AES stuff for the first time
|
|
214
|
+
if (!aes_init_done) aes_init(); // Fill up AES tables
|
|
215
|
+
|
|
216
|
+
const heap = new Uint32Array(buffer);
|
|
217
|
+
heap.set(aes_sbox, 0x0800 >> 2);
|
|
218
|
+
heap.set(aes_sinv, 0x0c00 >> 2);
|
|
219
|
+
|
|
220
|
+
for (let i = 0; i < 4; i++) {
|
|
221
|
+
heap.set(aes_enc[i], 0x1000 + 0x400 * i >> 2);
|
|
222
|
+
heap.set(aes_dec[i], 0x2000 + 0x400 * i >> 2);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Calculate AES key schedules.
|
|
226
|
+
* @instance
|
|
227
|
+
* @memberof AES_asm
|
|
228
|
+
* @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly)
|
|
229
|
+
* @param {number} k0 - key vector components
|
|
230
|
+
* @param {number} k1 - key vector components
|
|
231
|
+
* @param {number} k2 - key vector components
|
|
232
|
+
* @param {number} k3 - key vector components
|
|
233
|
+
* @param {number} k4 - key vector components
|
|
234
|
+
* @param {number} k5 - key vector components
|
|
235
|
+
* @param {number} k6 - key vector components
|
|
236
|
+
* @param {number} k7 - key vector components
|
|
237
|
+
*/
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) {
|
|
241
|
+
const ekeys = heap.subarray(0x000, 60),
|
|
242
|
+
dkeys = heap.subarray(0x100, 0x100 + 60); // Encryption key schedule
|
|
243
|
+
|
|
244
|
+
ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]);
|
|
245
|
+
let i = ks;
|
|
246
|
+
|
|
247
|
+
for (let rcon = 1; i < 4 * ks + 28; i++) {
|
|
248
|
+
let k = ekeys[i - 1];
|
|
249
|
+
|
|
250
|
+
if (i % ks === 0 || ks === 8 && i % ks === 4) {
|
|
251
|
+
k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255];
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (i % ks === 0) {
|
|
255
|
+
k = k << 8 ^ k >>> 24 ^ rcon << 24;
|
|
256
|
+
rcon = rcon << 1 ^ (rcon & 0x80 ? 0x1b : 0);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
ekeys[i] = ekeys[i - ks] ^ k;
|
|
260
|
+
} // Decryption key schedule
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
for (let j = 0; j < i; j += 4) {
|
|
264
|
+
for (let jj = 0; jj < 4; jj++) {
|
|
265
|
+
const kk = ekeys[i - (4 + j) + (4 - jj) % 4];
|
|
266
|
+
|
|
267
|
+
if (j < 4 || j >= i - 4) {
|
|
268
|
+
dkeys[j + jj] = kk;
|
|
269
|
+
} else {
|
|
270
|
+
dkeys[j + jj] = aes_dec[0][aes_sbox[kk >>> 24]] ^ aes_dec[1][aes_sbox[kk >>> 16 & 255]] ^ aes_dec[2][aes_sbox[kk >>> 8 & 255]] ^ aes_dec[3][aes_sbox[kk & 255]];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
} // Set rounds number
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
asm.set_rounds(ks + 5);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const asm = function (foreign, buffer) {
|
|
280
|
+
'use asm';
|
|
281
|
+
|
|
282
|
+
let S0 = 0,
|
|
283
|
+
S1 = 0,
|
|
284
|
+
S2 = 0,
|
|
285
|
+
S3 = 0,
|
|
286
|
+
I0 = 0,
|
|
287
|
+
I1 = 0,
|
|
288
|
+
I2 = 0,
|
|
289
|
+
I3 = 0,
|
|
290
|
+
N0 = 0,
|
|
291
|
+
N1 = 0,
|
|
292
|
+
N2 = 0,
|
|
293
|
+
N3 = 0,
|
|
294
|
+
M0 = 0,
|
|
295
|
+
M1 = 0,
|
|
296
|
+
M2 = 0,
|
|
297
|
+
M3 = 0,
|
|
298
|
+
H0 = 0,
|
|
299
|
+
H1 = 0,
|
|
300
|
+
H2 = 0,
|
|
301
|
+
H3 = 0,
|
|
302
|
+
R = 0;
|
|
303
|
+
const HEAP = new Uint32Array(buffer),
|
|
304
|
+
DATA = new Uint8Array(buffer);
|
|
305
|
+
/**
|
|
306
|
+
* AES core
|
|
307
|
+
* @param {number} k - precomputed key schedule offset
|
|
308
|
+
* @param {number} s - precomputed sbox table offset
|
|
309
|
+
* @param {number} t - precomputed round table offset
|
|
310
|
+
* @param {number} r - number of inner rounds to perform
|
|
311
|
+
* @param {number} x0 - 128-bit input block vector
|
|
312
|
+
* @param {number} x1 - 128-bit input block vector
|
|
313
|
+
* @param {number} x2 - 128-bit input block vector
|
|
314
|
+
* @param {number} x3 - 128-bit input block vector
|
|
315
|
+
*/
|
|
316
|
+
|
|
317
|
+
function _core(k, s, t, r, x0, x1, x2, x3) {
|
|
318
|
+
k = k | 0;
|
|
319
|
+
s = s | 0;
|
|
320
|
+
t = t | 0;
|
|
321
|
+
r = r | 0;
|
|
322
|
+
x0 = x0 | 0;
|
|
323
|
+
x1 = x1 | 0;
|
|
324
|
+
x2 = x2 | 0;
|
|
325
|
+
x3 = x3 | 0;
|
|
326
|
+
let t1 = 0,
|
|
327
|
+
t2 = 0,
|
|
328
|
+
t3 = 0,
|
|
329
|
+
y0 = 0,
|
|
330
|
+
y1 = 0,
|
|
331
|
+
y2 = 0,
|
|
332
|
+
y3 = 0,
|
|
333
|
+
i = 0;
|
|
334
|
+
t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00; // round 0
|
|
335
|
+
|
|
336
|
+
x0 = x0 ^ HEAP[(k | 0) >> 2], x1 = x1 ^ HEAP[(k | 4) >> 2], x2 = x2 ^ HEAP[(k | 8) >> 2], x3 = x3 ^ HEAP[(k | 12) >> 2]; // round 1..r
|
|
337
|
+
|
|
338
|
+
for (i = 16; (i | 0) <= r << 4; i = i + 16 | 0) {
|
|
339
|
+
y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2];
|
|
340
|
+
x0 = y0, x1 = y1, x2 = y2, x3 = y3;
|
|
341
|
+
} // final round
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2], S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2], S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2], S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2];
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* ECB mode encryption
|
|
348
|
+
* @param {number} x0 - 128-bit input block vector
|
|
349
|
+
* @param {number} x1 - 128-bit input block vector
|
|
350
|
+
* @param {number} x2 - 128-bit input block vector
|
|
351
|
+
* @param {number} x3 - 128-bit input block vector
|
|
352
|
+
*/
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
function _ecb_enc(x0, x1, x2, x3) {
|
|
356
|
+
x0 = x0 | 0;
|
|
357
|
+
x1 = x1 | 0;
|
|
358
|
+
x2 = x2 | 0;
|
|
359
|
+
x3 = x3 | 0;
|
|
360
|
+
|
|
361
|
+
_core(0x0000, 0x0800, 0x1000, R, x0, x1, x2, x3);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* ECB mode decryption
|
|
365
|
+
* @param {number} x0 - 128-bit input block vector
|
|
366
|
+
* @param {number} x1 - 128-bit input block vector
|
|
367
|
+
* @param {number} x2 - 128-bit input block vector
|
|
368
|
+
* @param {number} x3 - 128-bit input block vector
|
|
369
|
+
*/
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
function _ecb_dec(x0, x1, x2, x3) {
|
|
373
|
+
x0 = x0 | 0;
|
|
374
|
+
x1 = x1 | 0;
|
|
375
|
+
x2 = x2 | 0;
|
|
376
|
+
x3 = x3 | 0;
|
|
377
|
+
let t = 0;
|
|
378
|
+
|
|
379
|
+
_core(0x0400, 0x0c00, 0x2000, R, x0, x3, x2, x1);
|
|
380
|
+
|
|
381
|
+
t = S1, S1 = S3, S3 = t;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* CBC mode encryption
|
|
385
|
+
* @param {number} x0 - 128-bit input block vector
|
|
386
|
+
* @param {number} x1 - 128-bit input block vector
|
|
387
|
+
* @param {number} x2 - 128-bit input block vector
|
|
388
|
+
* @param {number} x3 - 128-bit input block vector
|
|
389
|
+
*/
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
function _cbc_enc(x0, x1, x2, x3) {
|
|
393
|
+
x0 = x0 | 0;
|
|
394
|
+
x1 = x1 | 0;
|
|
395
|
+
x2 = x2 | 0;
|
|
396
|
+
x3 = x3 | 0;
|
|
397
|
+
|
|
398
|
+
_core(0x0000, 0x0800, 0x1000, R, I0 ^ x0, I1 ^ x1, I2 ^ x2, I3 ^ x3);
|
|
399
|
+
|
|
400
|
+
I0 = S0, I1 = S1, I2 = S2, I3 = S3;
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* CBC mode decryption
|
|
404
|
+
* @param {number} x0 - 128-bit input block vector
|
|
405
|
+
* @param {number} x1 - 128-bit input block vector
|
|
406
|
+
* @param {number} x2 - 128-bit input block vector
|
|
407
|
+
* @param {number} x3 - 128-bit input block vector
|
|
408
|
+
*/
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
function _cbc_dec(x0, x1, x2, x3) {
|
|
412
|
+
x0 = x0 | 0;
|
|
413
|
+
x1 = x1 | 0;
|
|
414
|
+
x2 = x2 | 0;
|
|
415
|
+
x3 = x3 | 0;
|
|
416
|
+
let t = 0;
|
|
417
|
+
|
|
418
|
+
_core(0x0400, 0x0c00, 0x2000, R, x0, x3, x2, x1);
|
|
419
|
+
|
|
420
|
+
t = S1, S1 = S3, S3 = t;
|
|
421
|
+
S0 = S0 ^ I0, S1 = S1 ^ I1, S2 = S2 ^ I2, S3 = S3 ^ I3;
|
|
422
|
+
I0 = x0, I1 = x1, I2 = x2, I3 = x3;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* CFB mode encryption
|
|
426
|
+
* @param {number} x0 - 128-bit input block vector
|
|
427
|
+
* @param {number} x1 - 128-bit input block vector
|
|
428
|
+
* @param {number} x2 - 128-bit input block vector
|
|
429
|
+
* @param {number} x3 - 128-bit input block vector
|
|
430
|
+
*/
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
function _cfb_enc(x0, x1, x2, x3) {
|
|
434
|
+
x0 = x0 | 0;
|
|
435
|
+
x1 = x1 | 0;
|
|
436
|
+
x2 = x2 | 0;
|
|
437
|
+
x3 = x3 | 0;
|
|
438
|
+
|
|
439
|
+
_core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3);
|
|
440
|
+
|
|
441
|
+
I0 = S0 = S0 ^ x0, I1 = S1 = S1 ^ x1, I2 = S2 = S2 ^ x2, I3 = S3 = S3 ^ x3;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* CFB mode decryption
|
|
445
|
+
* @param {number} x0 - 128-bit input block vector
|
|
446
|
+
* @param {number} x1 - 128-bit input block vector
|
|
447
|
+
* @param {number} x2 - 128-bit input block vector
|
|
448
|
+
* @param {number} x3 - 128-bit input block vector
|
|
449
|
+
*/
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
function _cfb_dec(x0, x1, x2, x3) {
|
|
453
|
+
x0 = x0 | 0;
|
|
454
|
+
x1 = x1 | 0;
|
|
455
|
+
x2 = x2 | 0;
|
|
456
|
+
x3 = x3 | 0;
|
|
457
|
+
|
|
458
|
+
_core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3);
|
|
459
|
+
|
|
460
|
+
S0 = S0 ^ x0, S1 = S1 ^ x1, S2 = S2 ^ x2, S3 = S3 ^ x3;
|
|
461
|
+
I0 = x0, I1 = x1, I2 = x2, I3 = x3;
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* OFB mode encryption / decryption
|
|
465
|
+
* @param {number} x0 - 128-bit input block vector
|
|
466
|
+
* @param {number} x1 - 128-bit input block vector
|
|
467
|
+
* @param {number} x2 - 128-bit input block vector
|
|
468
|
+
* @param {number} x3 - 128-bit input block vector
|
|
469
|
+
*/
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
function _ofb(x0, x1, x2, x3) {
|
|
473
|
+
x0 = x0 | 0;
|
|
474
|
+
x1 = x1 | 0;
|
|
475
|
+
x2 = x2 | 0;
|
|
476
|
+
x3 = x3 | 0;
|
|
477
|
+
|
|
478
|
+
_core(0x0000, 0x0800, 0x1000, R, I0, I1, I2, I3);
|
|
479
|
+
|
|
480
|
+
I0 = S0, I1 = S1, I2 = S2, I3 = S3;
|
|
481
|
+
S0 = S0 ^ x0, S1 = S1 ^ x1, S2 = S2 ^ x2, S3 = S3 ^ x3;
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* CTR mode encryption / decryption
|
|
485
|
+
* @param {number} x0 - 128-bit input block vector
|
|
486
|
+
* @param {number} x1 - 128-bit input block vector
|
|
487
|
+
* @param {number} x2 - 128-bit input block vector
|
|
488
|
+
* @param {number} x3 - 128-bit input block vector
|
|
489
|
+
*/
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
function _ctr(x0, x1, x2, x3) {
|
|
493
|
+
x0 = x0 | 0;
|
|
494
|
+
x1 = x1 | 0;
|
|
495
|
+
x2 = x2 | 0;
|
|
496
|
+
x3 = x3 | 0;
|
|
497
|
+
|
|
498
|
+
_core(0x0000, 0x0800, 0x1000, R, N0, N1, N2, N3);
|
|
499
|
+
|
|
500
|
+
N3 = ~M3 & N3 | M3 & N3 + 1;
|
|
501
|
+
N2 = ~M2 & N2 | M2 & N2 + Number((N3 | 0) === 0);
|
|
502
|
+
N1 = ~M1 & N1 | M1 & N1 + Number((N2 | 0) === 0);
|
|
503
|
+
N0 = ~M0 & N0 | M0 & N0 + Number((N1 | 0) === 0);
|
|
504
|
+
S0 = S0 ^ x0;
|
|
505
|
+
S1 = S1 ^ x1;
|
|
506
|
+
S2 = S2 ^ x2;
|
|
507
|
+
S3 = S3 ^ x3;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* GCM mode MAC calculation
|
|
511
|
+
* @param {number} x0 - 128-bit input block vector
|
|
512
|
+
* @param {number} x1 - 128-bit input block vector
|
|
513
|
+
* @param {number} x2 - 128-bit input block vector
|
|
514
|
+
* @param {number} x3 - 128-bit input block vector
|
|
515
|
+
*/
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
function _gcm_mac(x0, x1, x2, x3) {
|
|
519
|
+
x0 = x0 | 0;
|
|
520
|
+
x1 = x1 | 0;
|
|
521
|
+
x2 = x2 | 0;
|
|
522
|
+
x3 = x3 | 0;
|
|
523
|
+
let y0 = 0,
|
|
524
|
+
y1 = 0,
|
|
525
|
+
y2 = 0,
|
|
526
|
+
y3 = 0,
|
|
527
|
+
z0 = 0,
|
|
528
|
+
z1 = 0,
|
|
529
|
+
z2 = 0,
|
|
530
|
+
z3 = 0,
|
|
531
|
+
i = 0,
|
|
532
|
+
c = 0;
|
|
533
|
+
x0 = x0 ^ I0, x1 = x1 ^ I1, x2 = x2 ^ I2, x3 = x3 ^ I3;
|
|
534
|
+
y0 = H0 | 0, y1 = H1 | 0, y2 = H2 | 0, y3 = H3 | 0;
|
|
535
|
+
|
|
536
|
+
for (; (i | 0) < 128; i = i + 1 | 0) {
|
|
537
|
+
if (y0 >>> 31) {
|
|
538
|
+
z0 = z0 ^ x0, z1 = z1 ^ x1, z2 = z2 ^ x2, z3 = z3 ^ x3;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
y0 = y0 << 1 | y1 >>> 31, y1 = y1 << 1 | y2 >>> 31, y2 = y2 << 1 | y3 >>> 31, y3 = y3 << 1;
|
|
542
|
+
c = x3 & 1;
|
|
543
|
+
x3 = x3 >>> 1 | x2 << 31, x2 = x2 >>> 1 | x1 << 31, x1 = x1 >>> 1 | x0 << 31, x0 = x0 >>> 1;
|
|
544
|
+
if (c) x0 = x0 ^ 0xe1000000;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
I0 = z0, I1 = z1, I2 = z2, I3 = z3;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Set the internal rounds number.
|
|
551
|
+
* @instance
|
|
552
|
+
* @memberof AES_asm
|
|
553
|
+
* @param {number} r - number if inner AES rounds
|
|
554
|
+
*/
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
function set_rounds(r) {
|
|
558
|
+
r = r | 0;
|
|
559
|
+
R = r;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Populate the internal state of the module.
|
|
563
|
+
* @instance
|
|
564
|
+
* @memberof AES_asm
|
|
565
|
+
* @param {number} s0 - state vector
|
|
566
|
+
* @param {number} s1 - state vector
|
|
567
|
+
* @param {number} s2 - state vector
|
|
568
|
+
* @param {number} s3 - state vector
|
|
569
|
+
*/
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
function set_state(s0, s1, s2, s3) {
|
|
573
|
+
s0 = s0 | 0;
|
|
574
|
+
s1 = s1 | 0;
|
|
575
|
+
s2 = s2 | 0;
|
|
576
|
+
s3 = s3 | 0;
|
|
577
|
+
S0 = s0, S1 = s1, S2 = s2, S3 = s3;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Populate the internal iv of the module.
|
|
581
|
+
* @instance
|
|
582
|
+
* @memberof AES_asm
|
|
583
|
+
* @param {number} i0 - iv vector
|
|
584
|
+
* @param {number} i1 - iv vector
|
|
585
|
+
* @param {number} i2 - iv vector
|
|
586
|
+
* @param {number} i3 - iv vector
|
|
587
|
+
*/
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
function set_iv(i0, i1, i2, i3) {
|
|
591
|
+
i0 = i0 | 0;
|
|
592
|
+
i1 = i1 | 0;
|
|
593
|
+
i2 = i2 | 0;
|
|
594
|
+
i3 = i3 | 0;
|
|
595
|
+
I0 = i0, I1 = i1, I2 = i2, I3 = i3;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Set nonce for CTR-family modes.
|
|
599
|
+
* @instance
|
|
600
|
+
* @memberof AES_asm
|
|
601
|
+
* @param {number} n0 - nonce vector
|
|
602
|
+
* @param {number} n1 - nonce vector
|
|
603
|
+
* @param {number} n2 - nonce vector
|
|
604
|
+
* @param {number} n3 - nonce vector
|
|
605
|
+
*/
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
function set_nonce(n0, n1, n2, n3) {
|
|
609
|
+
n0 = n0 | 0;
|
|
610
|
+
n1 = n1 | 0;
|
|
611
|
+
n2 = n2 | 0;
|
|
612
|
+
n3 = n3 | 0;
|
|
613
|
+
N0 = n0, N1 = n1, N2 = n2, N3 = n3;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Set counter mask for CTR-family modes.
|
|
617
|
+
* @instance
|
|
618
|
+
* @memberof AES_asm
|
|
619
|
+
* @param {number} m0 - counter mask vector
|
|
620
|
+
* @param {number} m1 - counter mask vector
|
|
621
|
+
* @param {number} m2 - counter mask vector
|
|
622
|
+
* @param {number} m3 - counter mask vector
|
|
623
|
+
*/
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
function set_mask(m0, m1, m2, m3) {
|
|
627
|
+
m0 = m0 | 0;
|
|
628
|
+
m1 = m1 | 0;
|
|
629
|
+
m2 = m2 | 0;
|
|
630
|
+
m3 = m3 | 0;
|
|
631
|
+
M0 = m0, M1 = m1, M2 = m2, M3 = m3;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Set counter for CTR-family modes.
|
|
635
|
+
* @instance
|
|
636
|
+
* @memberof AES_asm
|
|
637
|
+
* @param {number} c0 - counter vector
|
|
638
|
+
* @param {number} c1 - counter vector
|
|
639
|
+
* @param {number} c2 - counter vector
|
|
640
|
+
* @param {number} c3 - counter vector
|
|
641
|
+
*/
|
|
642
|
+
|
|
643
|
+
|
|
644
|
+
function set_counter(c0, c1, c2, c3) {
|
|
645
|
+
c0 = c0 | 0;
|
|
646
|
+
c1 = c1 | 0;
|
|
647
|
+
c2 = c2 | 0;
|
|
648
|
+
c3 = c3 | 0;
|
|
649
|
+
N3 = ~M3 & N3 | M3 & c3, N2 = ~M2 & N2 | M2 & c2, N1 = ~M1 & N1 | M1 & c1, N0 = ~M0 & N0 | M0 & c0;
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Store the internal state vector into the heap.
|
|
653
|
+
* @instance
|
|
654
|
+
* @memberof AES_asm
|
|
655
|
+
* @param {number} pos - offset where to put the data
|
|
656
|
+
* @return {number} The number of bytes have been written into the heap, always 16.
|
|
657
|
+
*/
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
function get_state(pos) {
|
|
661
|
+
pos = pos | 0;
|
|
662
|
+
if (pos & 15) return -1;
|
|
663
|
+
DATA[pos | 0] = S0 >>> 24, DATA[pos | 1] = S0 >>> 16 & 255, DATA[pos | 2] = S0 >>> 8 & 255, DATA[pos | 3] = S0 & 255, DATA[pos | 4] = S1 >>> 24, DATA[pos | 5] = S1 >>> 16 & 255, DATA[pos | 6] = S1 >>> 8 & 255, DATA[pos | 7] = S1 & 255, DATA[pos | 8] = S2 >>> 24, DATA[pos | 9] = S2 >>> 16 & 255, DATA[pos | 10] = S2 >>> 8 & 255, DATA[pos | 11] = S2 & 255, DATA[pos | 12] = S3 >>> 24, DATA[pos | 13] = S3 >>> 16 & 255, DATA[pos | 14] = S3 >>> 8 & 255, DATA[pos | 15] = S3 & 255;
|
|
664
|
+
return 16;
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Store the internal iv vector into the heap.
|
|
668
|
+
* @instance
|
|
669
|
+
* @memberof AES_asm
|
|
670
|
+
* @param {number} pos - offset where to put the data
|
|
671
|
+
* @return {number} The number of bytes have been written into the heap, always 16.
|
|
672
|
+
*/
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
function get_iv(pos) {
|
|
676
|
+
pos = pos | 0;
|
|
677
|
+
if (pos & 15) return -1;
|
|
678
|
+
DATA[pos | 0] = I0 >>> 24, DATA[pos | 1] = I0 >>> 16 & 255, DATA[pos | 2] = I0 >>> 8 & 255, DATA[pos | 3] = I0 & 255, DATA[pos | 4] = I1 >>> 24, DATA[pos | 5] = I1 >>> 16 & 255, DATA[pos | 6] = I1 >>> 8 & 255, DATA[pos | 7] = I1 & 255, DATA[pos | 8] = I2 >>> 24, DATA[pos | 9] = I2 >>> 16 & 255, DATA[pos | 10] = I2 >>> 8 & 255, DATA[pos | 11] = I2 & 255, DATA[pos | 12] = I3 >>> 24, DATA[pos | 13] = I3 >>> 16 & 255, DATA[pos | 14] = I3 >>> 8 & 255, DATA[pos | 15] = I3 & 255;
|
|
679
|
+
return 16;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* GCM initialization.
|
|
683
|
+
* @instance
|
|
684
|
+
* @memberof AES_asm
|
|
685
|
+
*/
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
function gcm_init() {
|
|
689
|
+
_ecb_enc(0, 0, 0, 0);
|
|
690
|
+
|
|
691
|
+
H0 = S0, H1 = S1, H2 = S2, H3 = S3;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Perform ciphering operation on the supplied data.
|
|
695
|
+
* @instance
|
|
696
|
+
* @memberof AES_asm
|
|
697
|
+
* @param {number} mode - block cipher mode (see {@link AES_asm} mode constants)
|
|
698
|
+
* @param {number} pos - offset of the data being processed
|
|
699
|
+
* @param {number} len - length of the data being processed
|
|
700
|
+
* @return {number} Actual amount of data have been processed.
|
|
701
|
+
*/
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
function cipher(mode, pos, len) {
|
|
705
|
+
mode = mode | 0;
|
|
706
|
+
pos = pos | 0;
|
|
707
|
+
len = len | 0;
|
|
708
|
+
let ret = 0;
|
|
709
|
+
if (pos & 15) return -1;
|
|
710
|
+
|
|
711
|
+
while ((len | 0) >= 16) {
|
|
712
|
+
_cipher_modes[mode & 7](DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]);
|
|
713
|
+
|
|
714
|
+
DATA[pos | 0] = S0 >>> 24, DATA[pos | 1] = S0 >>> 16 & 255, DATA[pos | 2] = S0 >>> 8 & 255, DATA[pos | 3] = S0 & 255, DATA[pos | 4] = S1 >>> 24, DATA[pos | 5] = S1 >>> 16 & 255, DATA[pos | 6] = S1 >>> 8 & 255, DATA[pos | 7] = S1 & 255, DATA[pos | 8] = S2 >>> 24, DATA[pos | 9] = S2 >>> 16 & 255, DATA[pos | 10] = S2 >>> 8 & 255, DATA[pos | 11] = S2 & 255, DATA[pos | 12] = S3 >>> 24, DATA[pos | 13] = S3 >>> 16 & 255, DATA[pos | 14] = S3 >>> 8 & 255, DATA[pos | 15] = S3 & 255;
|
|
715
|
+
ret = ret + 16 | 0, pos = pos + 16 | 0, len = len - 16 | 0;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
return ret | 0;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Calculates MAC of the supplied data.
|
|
722
|
+
* @instance
|
|
723
|
+
* @memberof AES_asm
|
|
724
|
+
* @param {number} mode - block cipher mode (see {@link AES_asm} mode constants)
|
|
725
|
+
* @param {number} pos - offset of the data being processed
|
|
726
|
+
* @param {number} len - length of the data being processed
|
|
727
|
+
* @return {number} Actual amount of data have been processed.
|
|
728
|
+
*/
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
function mac(mode, pos, len) {
|
|
732
|
+
mode = mode | 0;
|
|
733
|
+
pos = pos | 0;
|
|
734
|
+
len = len | 0;
|
|
735
|
+
let ret = 0;
|
|
736
|
+
if (pos & 15) return -1;
|
|
737
|
+
|
|
738
|
+
while ((len | 0) >= 16) {
|
|
739
|
+
_mac_modes[mode & 1](DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3], DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7], DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11], DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]);
|
|
740
|
+
|
|
741
|
+
ret = ret + 16 | 0, pos = pos + 16 | 0, len = len - 16 | 0;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
return ret | 0;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* AES cipher modes table (virual methods)
|
|
748
|
+
*/
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
const _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr];
|
|
752
|
+
/**
|
|
753
|
+
* AES MAC modes table (virual methods)
|
|
754
|
+
*/
|
|
755
|
+
|
|
756
|
+
const _mac_modes = [_cbc_enc, _gcm_mac];
|
|
757
|
+
/**
|
|
758
|
+
* Asm.js module exports
|
|
759
|
+
*/
|
|
760
|
+
|
|
761
|
+
return {
|
|
762
|
+
set_rounds: set_rounds,
|
|
763
|
+
set_state: set_state,
|
|
764
|
+
set_iv: set_iv,
|
|
765
|
+
set_nonce: set_nonce,
|
|
766
|
+
set_mask: set_mask,
|
|
767
|
+
set_counter: set_counter,
|
|
768
|
+
get_state: get_state,
|
|
769
|
+
get_iv: get_iv,
|
|
770
|
+
gcm_init: gcm_init,
|
|
771
|
+
cipher: cipher,
|
|
772
|
+
mac: mac,
|
|
773
|
+
set_key
|
|
774
|
+
};
|
|
775
|
+
}(foreign, buffer);
|
|
776
|
+
|
|
777
|
+
return asm;
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
class AES_asm {
|
|
781
|
+
constructor(foreign, heap) {
|
|
782
|
+
return wrapper(foreign, heap);
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* @param ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly)
|
|
786
|
+
* @param k0 - key vector components
|
|
787
|
+
* @param k1 - key vector components
|
|
788
|
+
* @param k2 - key vector components
|
|
789
|
+
* @param k3 - key vector components
|
|
790
|
+
* @param k4 - key vector components
|
|
791
|
+
* @param k5 - key vector components
|
|
792
|
+
* @param k6 - key vector components
|
|
793
|
+
* @param k7 - key vector components
|
|
794
|
+
*/
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) {// 此处不需要实现
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* Populate the internal iv of the module
|
|
802
|
+
*/
|
|
803
|
+
set_iv(i0, i1, i2, i3) {// 此处不需要实现
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Set counter mask for CTR-family modes
|
|
807
|
+
*/
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
set_mask(m0, m1, m2, m3) {// 此处不需要实现
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* Set nonce for CTR-family modes
|
|
814
|
+
*/
|
|
815
|
+
|
|
816
|
+
|
|
817
|
+
set_nonce(n0, n1, n2, n3) {// 此处不需要实现
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Set counter for CTR-family modes
|
|
822
|
+
*/
|
|
823
|
+
set_counter(c0, c1, c2, c3) {// 此处不需要实现
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* Perform ciphering operation on the supplied data
|
|
828
|
+
*
|
|
829
|
+
* @param mode - block cipher mode (see {@link AES_asm} mode constants)
|
|
830
|
+
* @param pos - offset of the data being processed
|
|
831
|
+
* @param len - length of the data being processed
|
|
832
|
+
* @return Actual amount of data have been processed
|
|
833
|
+
*/
|
|
834
|
+
cipher(mode, pos, len) {
|
|
835
|
+
// 此处实现忽略
|
|
836
|
+
return 0;
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* GCM initialization
|
|
840
|
+
*/
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
gcm_init() {// 此处不需要实现
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Store the internal iv vector into the heap
|
|
847
|
+
*
|
|
848
|
+
* @returns The number of bytes have been written into the heap, always 16
|
|
849
|
+
*/
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
get_iv(pos) {
|
|
853
|
+
// 此处实现忽略
|
|
854
|
+
return 16;
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Calculates MAC of the supplied data
|
|
858
|
+
*
|
|
859
|
+
* @param mode - block cipher mode (see {@link AES_asm} mode constants)
|
|
860
|
+
* @param pos - offset of the data being processed
|
|
861
|
+
* @param len - length of the data being processed
|
|
862
|
+
* @return Actual amount of data have been processed
|
|
863
|
+
*/
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
mac(mode, pos, len) {
|
|
867
|
+
// 此处实现忽略
|
|
868
|
+
return 0;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Store the internal state vector into the heap.
|
|
872
|
+
*
|
|
873
|
+
* @param pos - offset where to put the data
|
|
874
|
+
* @return The number of bytes have been written into the heap, always 16.
|
|
875
|
+
*/
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
get_state(pos) {
|
|
879
|
+
// 此处实现忽略
|
|
880
|
+
return 16;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* AES enciphering mode constants
|
|
886
|
+
* @enum {number}
|
|
887
|
+
* @const
|
|
888
|
+
*/
|
|
889
|
+
|
|
890
|
+
AES_asm.ENC = {
|
|
891
|
+
ECB: 0,
|
|
892
|
+
CBC: 2,
|
|
893
|
+
CFB: 4,
|
|
894
|
+
OFB: 6,
|
|
895
|
+
CTR: 7
|
|
896
|
+
};
|
|
897
|
+
/**
|
|
898
|
+
* AES deciphering mode constants
|
|
899
|
+
* @enum {number}
|
|
900
|
+
* @const
|
|
901
|
+
*/
|
|
902
|
+
|
|
903
|
+
AES_asm.DEC = {
|
|
904
|
+
ECB: 1,
|
|
905
|
+
CBC: 3,
|
|
906
|
+
CFB: 5,
|
|
907
|
+
OFB: 6,
|
|
908
|
+
CTR: 7
|
|
909
|
+
};
|
|
910
|
+
/**
|
|
911
|
+
* AES MAC mode constants
|
|
912
|
+
* @enum {number}
|
|
913
|
+
* @const
|
|
914
|
+
*/
|
|
915
|
+
|
|
916
|
+
AES_asm.MAC = {
|
|
917
|
+
CBC: 0,
|
|
918
|
+
GCM: 1
|
|
919
|
+
};
|
|
920
|
+
/**
|
|
921
|
+
* Heap data offset
|
|
922
|
+
* @type {number}
|
|
923
|
+
* @const
|
|
924
|
+
*/
|
|
925
|
+
|
|
926
|
+
AES_asm.HEAP_DATA = 0x4000;
|
|
927
|
+
|
|
928
|
+
class AES {
|
|
929
|
+
constructor(key, iv, padding = true, mode, heap, asm) {
|
|
930
|
+
this.pos = 0;
|
|
931
|
+
this.len = 0;
|
|
932
|
+
this.mode = mode; // The AES "worker"
|
|
933
|
+
|
|
934
|
+
this.heap = heap ? heap : _heap_init().subarray(AES_asm.HEAP_DATA);
|
|
935
|
+
this.asm = asm ? asm : new AES_asm(null, this.heap.buffer); // The AES object state
|
|
936
|
+
|
|
937
|
+
this.pos = 0;
|
|
938
|
+
this.len = 0; // Key
|
|
939
|
+
|
|
940
|
+
const keylen = key.length;
|
|
941
|
+
if (keylen !== 16 && keylen !== 24 && keylen !== 32) throw new IllegalArgumentError('illegal key size');
|
|
942
|
+
const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength);
|
|
943
|
+
this.asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0); // IV
|
|
944
|
+
|
|
945
|
+
if (iv !== undefined) {
|
|
946
|
+
if (iv.length !== 16) throw new IllegalArgumentError('illegal iv size');
|
|
947
|
+
const ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength);
|
|
948
|
+
this.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12));
|
|
949
|
+
} else {
|
|
950
|
+
this.asm.set_iv(0, 0, 0, 0);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
this.padding = padding;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
AES_Encrypt_process(data) {
|
|
957
|
+
if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
|
|
958
|
+
const asm = this.asm;
|
|
959
|
+
const heap = this.heap;
|
|
960
|
+
const amode = AES_asm.ENC[this.mode];
|
|
961
|
+
const hpos = AES_asm.HEAP_DATA;
|
|
962
|
+
let pos = this.pos;
|
|
963
|
+
let len = this.len;
|
|
964
|
+
let dpos = 0;
|
|
965
|
+
let dlen = data.length || 0;
|
|
966
|
+
let rpos = 0;
|
|
967
|
+
const rlen = len + dlen & -16;
|
|
968
|
+
let wlen = 0;
|
|
969
|
+
const result = new Uint8Array(rlen);
|
|
970
|
+
|
|
971
|
+
while (dlen > 0) {
|
|
972
|
+
wlen = _heap_write(heap, pos + len, data, dpos, dlen);
|
|
973
|
+
len += wlen;
|
|
974
|
+
dpos += wlen;
|
|
975
|
+
dlen -= wlen;
|
|
976
|
+
wlen = asm.cipher(amode, hpos + pos, len);
|
|
977
|
+
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
|
|
978
|
+
rpos += wlen;
|
|
979
|
+
|
|
980
|
+
if (wlen < len) {
|
|
981
|
+
pos += wlen;
|
|
982
|
+
len -= wlen;
|
|
983
|
+
} else {
|
|
984
|
+
pos = 0;
|
|
985
|
+
len = 0;
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
this.pos = pos;
|
|
990
|
+
this.len = len;
|
|
991
|
+
return result;
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
AES_Encrypt_finish() {
|
|
995
|
+
const asm = this.asm;
|
|
996
|
+
const heap = this.heap;
|
|
997
|
+
const amode = AES_asm.ENC[this.mode];
|
|
998
|
+
const hpos = AES_asm.HEAP_DATA;
|
|
999
|
+
const pos = this.pos;
|
|
1000
|
+
let len = this.len;
|
|
1001
|
+
const plen = 16 - len % 16;
|
|
1002
|
+
let rlen = len; // eslint-disable-next-line no-prototype-builtins
|
|
1003
|
+
|
|
1004
|
+
if (this.hasOwnProperty('padding')) {
|
|
1005
|
+
if (this.padding) {
|
|
1006
|
+
for (let p = 0; p < plen; ++p) {
|
|
1007
|
+
heap[pos + len + p] = plen;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
len += plen;
|
|
1011
|
+
rlen = len;
|
|
1012
|
+
} else if (len % 16) {
|
|
1013
|
+
throw new IllegalArgumentError('data length must be a multiple of the block size');
|
|
1014
|
+
}
|
|
1015
|
+
} else {
|
|
1016
|
+
len += plen;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
const result = new Uint8Array(rlen);
|
|
1020
|
+
if (len) asm.cipher(amode, hpos + pos, len);
|
|
1021
|
+
if (rlen) result.set(heap.subarray(pos, pos + rlen));
|
|
1022
|
+
this.pos = 0;
|
|
1023
|
+
this.len = 0;
|
|
1024
|
+
return result;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
AES_Decrypt_process(data) {
|
|
1028
|
+
if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
|
|
1029
|
+
const asm = this.asm;
|
|
1030
|
+
const heap = this.heap;
|
|
1031
|
+
const amode = AES_asm.DEC[this.mode];
|
|
1032
|
+
const hpos = AES_asm.HEAP_DATA;
|
|
1033
|
+
let pos = this.pos;
|
|
1034
|
+
let len = this.len;
|
|
1035
|
+
let dpos = 0;
|
|
1036
|
+
let dlen = data.length || 0;
|
|
1037
|
+
let rpos = 0;
|
|
1038
|
+
let rlen = len + dlen & -16;
|
|
1039
|
+
let plen = 0;
|
|
1040
|
+
let wlen = 0;
|
|
1041
|
+
|
|
1042
|
+
if (this.padding) {
|
|
1043
|
+
plen = len + dlen - rlen || 16;
|
|
1044
|
+
rlen -= plen;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
const result = new Uint8Array(rlen);
|
|
1048
|
+
|
|
1049
|
+
while (dlen > 0) {
|
|
1050
|
+
wlen = _heap_write(heap, pos + len, data, dpos, dlen);
|
|
1051
|
+
len += wlen;
|
|
1052
|
+
dpos += wlen;
|
|
1053
|
+
dlen -= wlen;
|
|
1054
|
+
wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0));
|
|
1055
|
+
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
|
|
1056
|
+
rpos += wlen;
|
|
1057
|
+
|
|
1058
|
+
if (wlen < len) {
|
|
1059
|
+
pos += wlen;
|
|
1060
|
+
len -= wlen;
|
|
1061
|
+
} else {
|
|
1062
|
+
pos = 0;
|
|
1063
|
+
len = 0;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
this.pos = pos;
|
|
1068
|
+
this.len = len;
|
|
1069
|
+
return result;
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
AES_Decrypt_finish() {
|
|
1073
|
+
const asm = this.asm;
|
|
1074
|
+
const heap = this.heap;
|
|
1075
|
+
const amode = AES_asm.DEC[this.mode];
|
|
1076
|
+
const hpos = AES_asm.HEAP_DATA;
|
|
1077
|
+
const pos = this.pos;
|
|
1078
|
+
let len = this.len;
|
|
1079
|
+
let rlen = len;
|
|
1080
|
+
|
|
1081
|
+
if (len > 0) {
|
|
1082
|
+
if (len % 16) {
|
|
1083
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
1084
|
+
if (this.hasOwnProperty('padding')) {
|
|
1085
|
+
throw new IllegalArgumentError('data length must be a multiple of the block size');
|
|
1086
|
+
} else {
|
|
1087
|
+
len += 16 - len % 16;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
asm.cipher(amode, hpos + pos, len); // eslint-disable-next-line no-prototype-builtins
|
|
1092
|
+
|
|
1093
|
+
if (this.hasOwnProperty('padding') && this.padding) {
|
|
1094
|
+
const pad = heap[pos + rlen - 1];
|
|
1095
|
+
if (pad < 1 || pad > 16 || pad > rlen) throw new SecurityError('bad padding');
|
|
1096
|
+
let pcheck = 0;
|
|
1097
|
+
|
|
1098
|
+
for (let i = pad; i > 1; i--) pcheck |= pad ^ heap[pos + rlen - i];
|
|
1099
|
+
|
|
1100
|
+
if (pcheck) throw new SecurityError('bad padding');
|
|
1101
|
+
rlen -= pad;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
const result = new Uint8Array(rlen);
|
|
1106
|
+
|
|
1107
|
+
if (rlen > 0) {
|
|
1108
|
+
result.set(heap.subarray(pos, pos + rlen));
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
this.pos = 0;
|
|
1112
|
+
this.len = 0;
|
|
1113
|
+
return result;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5
|
|
1119
|
+
|
|
1120
|
+
class AES_GCM {
|
|
1121
|
+
constructor(key, nonce, adata, tagSize = 16, aes) {
|
|
1122
|
+
this.tagSize = tagSize;
|
|
1123
|
+
this.gamma0 = 0;
|
|
1124
|
+
this.counter = 1;
|
|
1125
|
+
this.aes = aes ? aes : new AES(key, undefined, false, 'CTR'); // Init GCM
|
|
1126
|
+
|
|
1127
|
+
this.aes.asm.gcm_init(); // Tag size
|
|
1128
|
+
|
|
1129
|
+
if (this.tagSize < 4 || this.tagSize > 16) throw new IllegalArgumentError('illegal tagSize value'); // Nonce
|
|
1130
|
+
|
|
1131
|
+
const noncelen = nonce.length || 0;
|
|
1132
|
+
const noncebuf = new Uint8Array(16);
|
|
1133
|
+
|
|
1134
|
+
if (noncelen !== 12) {
|
|
1135
|
+
this._gcm_mac_process(nonce);
|
|
1136
|
+
|
|
1137
|
+
this.aes.heap[0] = 0;
|
|
1138
|
+
this.aes.heap[1] = 0;
|
|
1139
|
+
this.aes.heap[2] = 0;
|
|
1140
|
+
this.aes.heap[3] = 0;
|
|
1141
|
+
this.aes.heap[4] = 0;
|
|
1142
|
+
this.aes.heap[5] = 0;
|
|
1143
|
+
this.aes.heap[6] = 0;
|
|
1144
|
+
this.aes.heap[7] = 0;
|
|
1145
|
+
this.aes.heap[8] = 0;
|
|
1146
|
+
this.aes.heap[9] = 0;
|
|
1147
|
+
this.aes.heap[10] = 0;
|
|
1148
|
+
this.aes.heap[11] = noncelen >>> 29;
|
|
1149
|
+
this.aes.heap[12] = noncelen >>> 21 & 255;
|
|
1150
|
+
this.aes.heap[13] = noncelen >>> 13 & 255;
|
|
1151
|
+
this.aes.heap[14] = noncelen >>> 5 & 255;
|
|
1152
|
+
this.aes.heap[15] = noncelen << 3 & 255;
|
|
1153
|
+
this.aes.asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
|
|
1154
|
+
this.aes.asm.get_iv(AES_asm.HEAP_DATA);
|
|
1155
|
+
this.aes.asm.set_iv(0, 0, 0, 0);
|
|
1156
|
+
noncebuf.set(this.aes.heap.subarray(0, 16));
|
|
1157
|
+
} else {
|
|
1158
|
+
noncebuf.set(nonce);
|
|
1159
|
+
noncebuf[15] = 1;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
const nonceview = new DataView(noncebuf.buffer);
|
|
1163
|
+
this.gamma0 = nonceview.getUint32(12);
|
|
1164
|
+
this.aes.asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0);
|
|
1165
|
+
this.aes.asm.set_mask(0, 0, 0, 0xffffffff); // Associated data
|
|
1166
|
+
|
|
1167
|
+
if (adata !== undefined) {
|
|
1168
|
+
if (adata.length > _AES_GCM_data_maxLength) throw new IllegalArgumentError('illegal adata length');
|
|
1169
|
+
|
|
1170
|
+
if (adata.length) {
|
|
1171
|
+
this.adata = adata;
|
|
1172
|
+
|
|
1173
|
+
this._gcm_mac_process(adata);
|
|
1174
|
+
} else {
|
|
1175
|
+
this.adata = undefined;
|
|
1176
|
+
}
|
|
1177
|
+
} else {
|
|
1178
|
+
this.adata = undefined;
|
|
1179
|
+
} // Counter
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
if (this.counter < 1 || this.counter > 0xffffffff) throw new RangeError('counter must be a positive 32-bit integer');
|
|
1183
|
+
this.aes.asm.set_counter(0, 0, 0, this.gamma0 + this.counter | 0);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
static encrypt(cleartext, key, nonce, adata, tagsize) {
|
|
1187
|
+
return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext);
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
static decrypt(ciphertext, key, nonce, adata, tagsize) {
|
|
1191
|
+
return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
encrypt(data) {
|
|
1195
|
+
return this.AES_GCM_encrypt(data);
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
decrypt(data) {
|
|
1199
|
+
return this.AES_GCM_decrypt(data);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
AES_GCM_Encrypt_process(data) {
|
|
1203
|
+
let dpos = 0;
|
|
1204
|
+
let dlen = data.length || 0;
|
|
1205
|
+
const asm = this.aes.asm;
|
|
1206
|
+
const heap = this.aes.heap;
|
|
1207
|
+
let counter = this.counter;
|
|
1208
|
+
let pos = this.aes.pos;
|
|
1209
|
+
let len = this.aes.len;
|
|
1210
|
+
let rpos = 0;
|
|
1211
|
+
const rlen = len + dlen & -16;
|
|
1212
|
+
let wlen = 0;
|
|
1213
|
+
if ((counter - 1 << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow');
|
|
1214
|
+
const result = new Uint8Array(rlen);
|
|
1215
|
+
|
|
1216
|
+
while (dlen > 0) {
|
|
1217
|
+
wlen = _heap_write(heap, pos + len, data, dpos, dlen);
|
|
1218
|
+
len += wlen;
|
|
1219
|
+
dpos += wlen;
|
|
1220
|
+
dlen -= wlen;
|
|
1221
|
+
wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len);
|
|
1222
|
+
wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen);
|
|
1223
|
+
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
|
|
1224
|
+
counter += wlen >>> 4;
|
|
1225
|
+
rpos += wlen;
|
|
1226
|
+
|
|
1227
|
+
if (wlen < len) {
|
|
1228
|
+
pos += wlen;
|
|
1229
|
+
len -= wlen;
|
|
1230
|
+
} else {
|
|
1231
|
+
pos = 0;
|
|
1232
|
+
len = 0;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
this.counter = counter;
|
|
1237
|
+
this.aes.pos = pos;
|
|
1238
|
+
this.aes.len = len;
|
|
1239
|
+
return result;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
AES_GCM_Encrypt_finish() {
|
|
1243
|
+
const asm = this.aes.asm;
|
|
1244
|
+
const heap = this.aes.heap;
|
|
1245
|
+
const counter = this.counter;
|
|
1246
|
+
const tagSize = this.tagSize;
|
|
1247
|
+
const adata = this.adata;
|
|
1248
|
+
const pos = this.aes.pos;
|
|
1249
|
+
const len = this.aes.len;
|
|
1250
|
+
const result = new Uint8Array(len + tagSize);
|
|
1251
|
+
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len + 15 & -16);
|
|
1252
|
+
if (len) result.set(heap.subarray(pos, pos + len));
|
|
1253
|
+
let i = len;
|
|
1254
|
+
|
|
1255
|
+
for (; i & 15; i++) heap[pos + i] = 0;
|
|
1256
|
+
|
|
1257
|
+
asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i);
|
|
1258
|
+
const alen = adata !== undefined ? adata.length : 0;
|
|
1259
|
+
const clen = (counter - 1 << 4) + len;
|
|
1260
|
+
heap[0] = 0;
|
|
1261
|
+
heap[1] = 0;
|
|
1262
|
+
heap[2] = 0;
|
|
1263
|
+
heap[3] = alen >>> 29;
|
|
1264
|
+
heap[4] = alen >>> 21;
|
|
1265
|
+
heap[5] = alen >>> 13 & 255;
|
|
1266
|
+
heap[6] = alen >>> 5 & 255;
|
|
1267
|
+
heap[7] = alen << 3 & 255;
|
|
1268
|
+
heap[8] = heap[9] = heap[10] = 0;
|
|
1269
|
+
heap[11] = clen >>> 29;
|
|
1270
|
+
heap[12] = clen >>> 21 & 255;
|
|
1271
|
+
heap[13] = clen >>> 13 & 255;
|
|
1272
|
+
heap[14] = clen >>> 5 & 255;
|
|
1273
|
+
heap[15] = clen << 3 & 255;
|
|
1274
|
+
asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
|
|
1275
|
+
asm.get_iv(AES_asm.HEAP_DATA);
|
|
1276
|
+
asm.set_counter(0, 0, 0, this.gamma0);
|
|
1277
|
+
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
|
|
1278
|
+
result.set(heap.subarray(0, tagSize), len);
|
|
1279
|
+
this.counter = 1;
|
|
1280
|
+
this.aes.pos = 0;
|
|
1281
|
+
this.aes.len = 0;
|
|
1282
|
+
return result;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
AES_GCM_Decrypt_process(data) {
|
|
1286
|
+
let dpos = 0;
|
|
1287
|
+
let dlen = data.length || 0;
|
|
1288
|
+
const asm = this.aes.asm;
|
|
1289
|
+
const heap = this.aes.heap;
|
|
1290
|
+
let counter = this.counter;
|
|
1291
|
+
const tagSize = this.tagSize;
|
|
1292
|
+
let pos = this.aes.pos;
|
|
1293
|
+
let len = this.aes.len;
|
|
1294
|
+
let rpos = 0;
|
|
1295
|
+
const rlen = len + dlen > tagSize ? len + dlen - tagSize & -16 : 0;
|
|
1296
|
+
const tlen = len + dlen - rlen;
|
|
1297
|
+
let wlen = 0;
|
|
1298
|
+
if ((counter - 1 << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow');
|
|
1299
|
+
const result = new Uint8Array(rlen);
|
|
1300
|
+
|
|
1301
|
+
while (dlen > tlen) {
|
|
1302
|
+
wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen);
|
|
1303
|
+
len += wlen;
|
|
1304
|
+
dpos += wlen;
|
|
1305
|
+
dlen -= wlen;
|
|
1306
|
+
wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen);
|
|
1307
|
+
wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen);
|
|
1308
|
+
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
|
|
1309
|
+
counter += wlen >>> 4;
|
|
1310
|
+
rpos += wlen;
|
|
1311
|
+
pos = 0;
|
|
1312
|
+
len = 0;
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
if (dlen > 0) {
|
|
1316
|
+
len += _heap_write(heap, 0, data, dpos, dlen);
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
this.counter = counter;
|
|
1320
|
+
this.aes.pos = pos;
|
|
1321
|
+
this.aes.len = len;
|
|
1322
|
+
return result;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
AES_GCM_Decrypt_finish() {
|
|
1326
|
+
const asm = this.aes.asm;
|
|
1327
|
+
const heap = this.aes.heap;
|
|
1328
|
+
const tagSize = this.tagSize;
|
|
1329
|
+
const adata = this.adata;
|
|
1330
|
+
const counter = this.counter;
|
|
1331
|
+
const pos = this.aes.pos;
|
|
1332
|
+
const len = this.aes.len;
|
|
1333
|
+
const rlen = len - tagSize;
|
|
1334
|
+
if (len < tagSize) throw new IllegalStateError('authentication tag not found');
|
|
1335
|
+
const result = new Uint8Array(rlen);
|
|
1336
|
+
const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len));
|
|
1337
|
+
let i = rlen;
|
|
1338
|
+
|
|
1339
|
+
for (; i & 15; i++) heap[pos + i] = 0;
|
|
1340
|
+
|
|
1341
|
+
asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i);
|
|
1342
|
+
asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i);
|
|
1343
|
+
if (rlen) result.set(heap.subarray(pos, pos + rlen));
|
|
1344
|
+
const alen = adata !== undefined ? adata.length : 0;
|
|
1345
|
+
const clen = (counter - 1 << 4) + len - tagSize;
|
|
1346
|
+
heap[0] = 0;
|
|
1347
|
+
heap[1] = 0;
|
|
1348
|
+
heap[2] = 0;
|
|
1349
|
+
heap[3] = alen >>> 29;
|
|
1350
|
+
heap[4] = alen >>> 21;
|
|
1351
|
+
heap[5] = alen >>> 13 & 255;
|
|
1352
|
+
heap[6] = alen >>> 5 & 255;
|
|
1353
|
+
heap[7] = alen << 3 & 255;
|
|
1354
|
+
heap[8] = heap[9] = heap[10] = 0;
|
|
1355
|
+
heap[11] = clen >>> 29;
|
|
1356
|
+
heap[12] = clen >>> 21 & 255;
|
|
1357
|
+
heap[13] = clen >>> 13 & 255;
|
|
1358
|
+
heap[14] = clen >>> 5 & 255;
|
|
1359
|
+
heap[15] = clen << 3 & 255;
|
|
1360
|
+
asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
|
|
1361
|
+
asm.get_iv(AES_asm.HEAP_DATA);
|
|
1362
|
+
asm.set_counter(0, 0, 0, this.gamma0);
|
|
1363
|
+
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
|
|
1364
|
+
let acheck = 0;
|
|
1365
|
+
|
|
1366
|
+
for (let _i = 0; _i < tagSize; ++_i) acheck |= atag[_i] ^ heap[_i];
|
|
1367
|
+
|
|
1368
|
+
if (acheck) throw new SecurityError('data integrity check failed');
|
|
1369
|
+
this.counter = 1;
|
|
1370
|
+
this.aes.pos = 0;
|
|
1371
|
+
this.aes.len = 0;
|
|
1372
|
+
return result;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
AES_GCM_decrypt(data) {
|
|
1376
|
+
const result1 = this.AES_GCM_Decrypt_process(data);
|
|
1377
|
+
const result2 = this.AES_GCM_Decrypt_finish();
|
|
1378
|
+
const result = new Uint8Array(result1.length + result2.length);
|
|
1379
|
+
if (result1.length) result.set(result1);
|
|
1380
|
+
if (result2.length) result.set(result2, result1.length);
|
|
1381
|
+
return result;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
AES_GCM_encrypt(data) {
|
|
1385
|
+
const result1 = this.AES_GCM_Encrypt_process(data);
|
|
1386
|
+
const result2 = this.AES_GCM_Encrypt_finish();
|
|
1387
|
+
const result = new Uint8Array(result1.length + result2.length);
|
|
1388
|
+
if (result1.length) result.set(result1);
|
|
1389
|
+
if (result2.length) result.set(result2, result1.length);
|
|
1390
|
+
return result;
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
_gcm_mac_process(data) {
|
|
1394
|
+
const heap = this.aes.heap;
|
|
1395
|
+
const asm = this.aes.asm;
|
|
1396
|
+
let dpos = 0;
|
|
1397
|
+
let dlen = data.length || 0;
|
|
1398
|
+
let wlen = 0;
|
|
1399
|
+
|
|
1400
|
+
while (dlen > 0) {
|
|
1401
|
+
wlen = _heap_write(heap, 0, data, dpos, dlen);
|
|
1402
|
+
dpos += wlen;
|
|
1403
|
+
dlen -= wlen;
|
|
1404
|
+
|
|
1405
|
+
while (wlen & 15) heap[wlen++] = 0;
|
|
1406
|
+
|
|
1407
|
+
asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
class AES_ECB {
|
|
1414
|
+
constructor(key, padding = false, aes) {
|
|
1415
|
+
this.aes = aes ? aes : new AES(key, undefined, padding, 'ECB');
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
static encrypt(data, key, padding = false) {
|
|
1419
|
+
return new AES_ECB(key, padding).encrypt(data);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
static decrypt(data, key, padding = false) {
|
|
1423
|
+
return new AES_ECB(key, padding).decrypt(data);
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
encrypt(data) {
|
|
1427
|
+
const r1 = this.aes.AES_Encrypt_process(data);
|
|
1428
|
+
const r2 = this.aes.AES_Encrypt_finish();
|
|
1429
|
+
return joinBytes(r1, r2);
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
decrypt(data) {
|
|
1433
|
+
const r1 = this.aes.AES_Decrypt_process(data);
|
|
1434
|
+
const r2 = this.aes.AES_Decrypt_finish();
|
|
1435
|
+
return joinBytes(r1, r2);
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
class AES_CBC {
|
|
1441
|
+
constructor(key, iv, padding = true, aes) {
|
|
1442
|
+
this.aes = aes ? aes : new AES(key, iv, padding, 'CBC');
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
static encrypt(data, key, padding = true, iv) {
|
|
1446
|
+
return new AES_CBC(key, iv, padding).encrypt(data);
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
static decrypt(data, key, padding = true, iv) {
|
|
1450
|
+
return new AES_CBC(key, iv, padding).decrypt(data);
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
encrypt(data) {
|
|
1454
|
+
const r1 = this.aes.AES_Encrypt_process(data);
|
|
1455
|
+
const r2 = this.aes.AES_Encrypt_finish();
|
|
1456
|
+
return joinBytes(r1, r2);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
decrypt(data) {
|
|
1460
|
+
const r1 = this.aes.AES_Decrypt_process(data);
|
|
1461
|
+
const r2 = this.aes.AES_Decrypt_finish();
|
|
1462
|
+
return joinBytes(r1, r2);
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
/**
|
|
1468
|
+
* Counter with CBC-MAC (CCM)
|
|
1469
|
+
*
|
|
1470
|
+
* Due to JS limitations (52 bits of Number precision) maximum encrypted message length
|
|
1471
|
+
* is limited to ~4 PiB ( 2^52 - 16 ) per `nonce`-`key` pair.
|
|
1472
|
+
* That also limits `lengthSize` parameter maximum value to 7 (not 8 as described in RFC3610).
|
|
1473
|
+
*
|
|
1474
|
+
* Additional authenticated data `adata` maximum length is chosen to be no more than 65279 bytes ( 2^16 - 2^8 ),
|
|
1475
|
+
* which is considered enough for the most of use-cases.
|
|
1476
|
+
*
|
|
1477
|
+
* And one more important thing: in case of progressive ciphering of a data stream (in other
|
|
1478
|
+
* words when data can't be held in-memory at a whole and are ciphered chunk-by-chunk)
|
|
1479
|
+
* you have to know the `dataLength` in advance and pass that value to the cipher options.
|
|
1480
|
+
*/
|
|
1481
|
+
const _AES_CCM_adata_maxLength = 65279; // 2^16 - 2^8
|
|
1482
|
+
|
|
1483
|
+
const _AES_CCM_data_maxLength = 4503599627370480; // 2^52 - 2^4
|
|
1484
|
+
|
|
1485
|
+
class AES_CCM {
|
|
1486
|
+
constructor(key, nonce, adata, tagSize = 16, dataLength, aes) {
|
|
1487
|
+
this.counter = 1;
|
|
1488
|
+
this.dataLength = -1;
|
|
1489
|
+
this.aes = aes ? aes : new AES(key, undefined, undefined, 'CCM'); // Tag size
|
|
1490
|
+
|
|
1491
|
+
if (tagSize < 4 || tagSize > 16 || tagSize & 1) throw new IllegalArgumentError('illegal tagSize value');
|
|
1492
|
+
this.tagSize = tagSize; // Nonce
|
|
1493
|
+
|
|
1494
|
+
this.nonce = nonce;
|
|
1495
|
+
if (nonce.length < 8 || nonce.length > 13) throw new IllegalArgumentError('illegal nonce length');
|
|
1496
|
+
this.lengthSize = 15 - nonce.length;
|
|
1497
|
+
nonce = new Uint8Array(nonce.length + 1);
|
|
1498
|
+
nonce[0] = this.lengthSize - 1;
|
|
1499
|
+
nonce.set(this.nonce, 1);
|
|
1500
|
+
if (dataLength < 0 || dataLength > _AES_CCM_data_maxLength || dataLength > Math.pow(2, 8 * this.lengthSize) - 16) throw new IllegalArgumentError('illegal dataLength value');
|
|
1501
|
+
|
|
1502
|
+
if (adata !== undefined) {
|
|
1503
|
+
if (adata.length > _AES_CCM_adata_maxLength) throw new IllegalArgumentError('illegal adata length');
|
|
1504
|
+
this.adata = adata.length ? adata : undefined;
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
this.dataLength = dataLength;
|
|
1508
|
+
this.counter = 1;
|
|
1509
|
+
this.AES_CCM_calculate_iv();
|
|
1510
|
+
this.AES_CTR_set_options(nonce, this.counter, 8 * this.lengthSize);
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
static encrypt(clear, key, nonce, adata, tagsize = 16) {
|
|
1514
|
+
return new AES_CCM(key, nonce, adata, tagsize, clear.length).encrypt(clear);
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
static decrypt(cipher, key, nonce, adata, tagsize = 16) {
|
|
1518
|
+
return new AES_CCM(key, nonce, adata, tagsize, cipher.length - tagsize).decrypt(cipher);
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
encrypt(data) {
|
|
1522
|
+
this.dataLength = data.length || 0;
|
|
1523
|
+
const result1 = this.AES_CCM_Encrypt_process(data);
|
|
1524
|
+
const result2 = this.AES_CCM_Encrypt_finish();
|
|
1525
|
+
const result = new Uint8Array(result1.length + result2.length);
|
|
1526
|
+
if (result1.length) result.set(result1);
|
|
1527
|
+
if (result2.length) result.set(result2, result1.length);
|
|
1528
|
+
return result;
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
decrypt(data) {
|
|
1532
|
+
this.dataLength = data.length || 0;
|
|
1533
|
+
const result1 = this.AES_CCM_Decrypt_process(data);
|
|
1534
|
+
const result2 = this.AES_CCM_Decrypt_finish();
|
|
1535
|
+
const result = new Uint8Array(result1.length + result2.length);
|
|
1536
|
+
if (result1.length) result.set(result1);
|
|
1537
|
+
if (result2.length) result.set(result2, result1.length);
|
|
1538
|
+
return result;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
AES_CCM_calculate_iv() {
|
|
1542
|
+
const nonce = this.nonce;
|
|
1543
|
+
const adata = this.adata;
|
|
1544
|
+
const tagSize = this.tagSize;
|
|
1545
|
+
const lengthSize = this.lengthSize;
|
|
1546
|
+
const dataLength = this.dataLength;
|
|
1547
|
+
const data = new Uint8Array(16 + (adata ? 2 + adata.length : 0)); // B0: flags(adata?, M', L'), nonce, len(data)
|
|
1548
|
+
|
|
1549
|
+
data[0] = (adata ? 64 : 0) | tagSize - 2 << 2 | lengthSize - 1;
|
|
1550
|
+
data.set(nonce, 1);
|
|
1551
|
+
if (lengthSize > 6) data[9] = dataLength / 0x100000000 >>> 16 & 15;
|
|
1552
|
+
if (lengthSize > 5) data[10] = dataLength / 0x100000000 >>> 8 & 255;
|
|
1553
|
+
if (lengthSize > 4) data[11] = dataLength / 0x100000000 & 255;
|
|
1554
|
+
if (lengthSize > 3) data[12] = dataLength >>> 24;
|
|
1555
|
+
if (lengthSize > 2) data[13] = dataLength >>> 16 & 255;
|
|
1556
|
+
data[14] = dataLength >>> 8 & 255;
|
|
1557
|
+
data[15] = dataLength & 255; // B*: len(adata), adata
|
|
1558
|
+
|
|
1559
|
+
if (adata) {
|
|
1560
|
+
data[16] = adata.length >>> 8 & 255;
|
|
1561
|
+
data[17] = adata.length & 255;
|
|
1562
|
+
data.set(adata, 18);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
this._cbc_mac_process(data);
|
|
1566
|
+
|
|
1567
|
+
this.aes.asm.get_state(AES_asm.HEAP_DATA);
|
|
1568
|
+
const iv = new Uint8Array(this.aes.heap.subarray(0, 16));
|
|
1569
|
+
const ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength);
|
|
1570
|
+
this.aes.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12));
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
_cbc_mac_process(data) {
|
|
1574
|
+
const heap = this.aes.heap;
|
|
1575
|
+
const asm = this.aes.asm;
|
|
1576
|
+
let dpos = 0;
|
|
1577
|
+
let dlen = data.length || 0;
|
|
1578
|
+
let wlen = 0;
|
|
1579
|
+
|
|
1580
|
+
while (dlen > 0) {
|
|
1581
|
+
wlen = _heap_write(heap, 0, data, dpos, dlen);
|
|
1582
|
+
|
|
1583
|
+
while (wlen & 15) heap[wlen++] = 0;
|
|
1584
|
+
|
|
1585
|
+
dpos += wlen;
|
|
1586
|
+
dlen -= wlen;
|
|
1587
|
+
asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA, wlen);
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
AES_CCM_Encrypt_process(data) {
|
|
1592
|
+
const asm = this.aes.asm;
|
|
1593
|
+
const heap = this.aes.heap;
|
|
1594
|
+
let dpos = 0;
|
|
1595
|
+
let dlen = data.length || 0;
|
|
1596
|
+
let counter = this.counter;
|
|
1597
|
+
let pos = this.aes.pos;
|
|
1598
|
+
let len = this.aes.len;
|
|
1599
|
+
const rlen = len + dlen & -16;
|
|
1600
|
+
let rpos = 0;
|
|
1601
|
+
let wlen = 0;
|
|
1602
|
+
if ((counter - 1 << 4) + len + dlen > _AES_CCM_data_maxLength) // ??? should check against lengthSize
|
|
1603
|
+
throw new RangeError('counter overflow');
|
|
1604
|
+
const result = new Uint8Array(rlen);
|
|
1605
|
+
|
|
1606
|
+
while (dlen > 0) {
|
|
1607
|
+
wlen = _heap_write(heap, pos + len, data, dpos, dlen);
|
|
1608
|
+
len += wlen;
|
|
1609
|
+
dpos += wlen;
|
|
1610
|
+
dlen -= wlen;
|
|
1611
|
+
wlen = asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, len);
|
|
1612
|
+
wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, wlen);
|
|
1613
|
+
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
|
|
1614
|
+
counter += wlen >>> 4;
|
|
1615
|
+
rpos += wlen;
|
|
1616
|
+
|
|
1617
|
+
if (wlen < len) {
|
|
1618
|
+
pos += wlen;
|
|
1619
|
+
len -= wlen;
|
|
1620
|
+
} else {
|
|
1621
|
+
pos = 0;
|
|
1622
|
+
len = 0;
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
this.counter = counter;
|
|
1627
|
+
this.aes.pos = pos;
|
|
1628
|
+
this.aes.len = len;
|
|
1629
|
+
return result;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
AES_CCM_Encrypt_finish() {
|
|
1633
|
+
const asm = this.aes.asm;
|
|
1634
|
+
const heap = this.aes.heap;
|
|
1635
|
+
const tagSize = this.tagSize;
|
|
1636
|
+
const pos = this.aes.pos;
|
|
1637
|
+
const len = this.aes.len;
|
|
1638
|
+
const result = new Uint8Array(len + tagSize);
|
|
1639
|
+
let i = len;
|
|
1640
|
+
|
|
1641
|
+
for (; i & 15; i++) heap[pos + i] = 0;
|
|
1642
|
+
|
|
1643
|
+
asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, i);
|
|
1644
|
+
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, i);
|
|
1645
|
+
if (len) result.set(heap.subarray(pos, pos + len));
|
|
1646
|
+
asm.set_counter(0, 0, 0, 0);
|
|
1647
|
+
asm.get_iv(AES_asm.HEAP_DATA);
|
|
1648
|
+
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
|
|
1649
|
+
result.set(heap.subarray(0, tagSize), len);
|
|
1650
|
+
this.counter = 1;
|
|
1651
|
+
this.aes.pos = 0;
|
|
1652
|
+
this.aes.len = 0;
|
|
1653
|
+
return result;
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
AES_CCM_Decrypt_process(data) {
|
|
1657
|
+
let dpos = 0;
|
|
1658
|
+
let dlen = data.length || 0;
|
|
1659
|
+
const asm = this.aes.asm;
|
|
1660
|
+
const heap = this.aes.heap;
|
|
1661
|
+
let counter = this.counter;
|
|
1662
|
+
const tagSize = this.tagSize;
|
|
1663
|
+
let pos = this.aes.pos;
|
|
1664
|
+
let len = this.aes.len;
|
|
1665
|
+
let rpos = 0;
|
|
1666
|
+
const rlen = len + dlen > tagSize ? len + dlen - tagSize & -16 : 0;
|
|
1667
|
+
const tlen = len + dlen - rlen;
|
|
1668
|
+
let wlen = 0;
|
|
1669
|
+
if ((counter - 1 << 4) + len + dlen > _AES_CCM_data_maxLength) throw new RangeError('counter overflow');
|
|
1670
|
+
const result = new Uint8Array(rlen);
|
|
1671
|
+
|
|
1672
|
+
while (dlen > tlen) {
|
|
1673
|
+
wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen);
|
|
1674
|
+
len += wlen;
|
|
1675
|
+
dpos += wlen;
|
|
1676
|
+
dlen -= wlen;
|
|
1677
|
+
wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen);
|
|
1678
|
+
wlen = asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, wlen);
|
|
1679
|
+
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
|
|
1680
|
+
counter += wlen >>> 4;
|
|
1681
|
+
rpos += wlen;
|
|
1682
|
+
pos = 0;
|
|
1683
|
+
len = 0;
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
if (dlen > 0) {
|
|
1687
|
+
len += _heap_write(heap, 0, data, dpos, dlen);
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
this.counter = counter;
|
|
1691
|
+
this.aes.pos = pos;
|
|
1692
|
+
this.aes.len = len;
|
|
1693
|
+
return result;
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
AES_CCM_Decrypt_finish() {
|
|
1697
|
+
const asm = this.aes.asm;
|
|
1698
|
+
const heap = this.aes.heap;
|
|
1699
|
+
const tagSize = this.tagSize;
|
|
1700
|
+
const pos = this.aes.pos;
|
|
1701
|
+
const len = this.aes.len;
|
|
1702
|
+
const rlen = len - tagSize;
|
|
1703
|
+
if (len < tagSize) throw new IllegalStateError('authentication tag not found');
|
|
1704
|
+
const result = new Uint8Array(rlen);
|
|
1705
|
+
const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len));
|
|
1706
|
+
asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, rlen + 15 & -16);
|
|
1707
|
+
result.set(heap.subarray(pos, pos + rlen));
|
|
1708
|
+
let i = rlen;
|
|
1709
|
+
|
|
1710
|
+
for (; i & 15; i++) heap[pos + i] = 0;
|
|
1711
|
+
|
|
1712
|
+
asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, i);
|
|
1713
|
+
asm.set_counter(0, 0, 0, 0);
|
|
1714
|
+
asm.get_iv(AES_asm.HEAP_DATA);
|
|
1715
|
+
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
|
|
1716
|
+
let acheck = 0;
|
|
1717
|
+
|
|
1718
|
+
for (let j = 0; j < tagSize; ++j) acheck |= atag[j] ^ heap[j];
|
|
1719
|
+
|
|
1720
|
+
if (acheck) throw new SecurityError('data integrity check failed');
|
|
1721
|
+
this.counter = 1;
|
|
1722
|
+
this.aes.pos = 0;
|
|
1723
|
+
this.aes.len = 0;
|
|
1724
|
+
return result;
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
AES_CTR_set_options(nonce, counter, size) {
|
|
1728
|
+
if (size < 8 || size > 48) throw new IllegalArgumentError('illegal counter size');
|
|
1729
|
+
const mask = Math.pow(2, size) - 1;
|
|
1730
|
+
this.aes.asm.set_mask(0, 0, mask / 0x100000000 | 0, mask | 0);
|
|
1731
|
+
const len = nonce.length;
|
|
1732
|
+
if (!len || len > 16) throw new IllegalArgumentError('illegal nonce size');
|
|
1733
|
+
this.nonce = nonce;
|
|
1734
|
+
const view = new DataView(new ArrayBuffer(16));
|
|
1735
|
+
new Uint8Array(view.buffer).set(nonce);
|
|
1736
|
+
this.aes.asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12));
|
|
1737
|
+
if (counter < 0 || counter >= Math.pow(2, size)) throw new IllegalArgumentError('illegal counter value');
|
|
1738
|
+
this.counter = counter;
|
|
1739
|
+
this.aes.asm.set_counter(0, 0, counter / 0x100000000 | 0, counter | 0);
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
exports.AES = AES;
|
|
1745
|
+
exports.AES_CBC = AES_CBC;
|
|
1746
|
+
exports.AES_CCM = AES_CCM;
|
|
1747
|
+
exports.AES_ECB = AES_ECB;
|
|
1748
|
+
exports.AES_GCM = AES_GCM;
|
|
1749
|
+
exports.IllegalArgumentError = IllegalArgumentError;
|
|
1750
|
+
exports.IllegalStateError = IllegalStateError;
|
|
1751
|
+
exports.SecurityError = SecurityError;
|