@gjsify/crypto 0.3.12 → 0.3.14

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/lib/esm/cipher.js CHANGED
@@ -1,1272 +1,1295 @@
1
1
  import { Buffer } from "node:buffer";
2
+
3
+ //#region src/cipher.ts
2
4
  const SBOX = new Uint8Array([
3
- 99,
4
- 124,
5
- 119,
6
- 123,
7
- 242,
8
- 107,
9
- 111,
10
- 197,
11
- 48,
12
- 1,
13
- 103,
14
- 43,
15
- 254,
16
- 215,
17
- 171,
18
- 118,
19
- 202,
20
- 130,
21
- 201,
22
- 125,
23
- 250,
24
- 89,
25
- 71,
26
- 240,
27
- 173,
28
- 212,
29
- 162,
30
- 175,
31
- 156,
32
- 164,
33
- 114,
34
- 192,
35
- 183,
36
- 253,
37
- 147,
38
- 38,
39
- 54,
40
- 63,
41
- 247,
42
- 204,
43
- 52,
44
- 165,
45
- 229,
46
- 241,
47
- 113,
48
- 216,
49
- 49,
50
- 21,
51
- 4,
52
- 199,
53
- 35,
54
- 195,
55
- 24,
56
- 150,
57
- 5,
58
- 154,
59
- 7,
60
- 18,
61
- 128,
62
- 226,
63
- 235,
64
- 39,
65
- 178,
66
- 117,
67
- 9,
68
- 131,
69
- 44,
70
- 26,
71
- 27,
72
- 110,
73
- 90,
74
- 160,
75
- 82,
76
- 59,
77
- 214,
78
- 179,
79
- 41,
80
- 227,
81
- 47,
82
- 132,
83
- 83,
84
- 209,
85
- 0,
86
- 237,
87
- 32,
88
- 252,
89
- 177,
90
- 91,
91
- 106,
92
- 203,
93
- 190,
94
- 57,
95
- 74,
96
- 76,
97
- 88,
98
- 207,
99
- 208,
100
- 239,
101
- 170,
102
- 251,
103
- 67,
104
- 77,
105
- 51,
106
- 133,
107
- 69,
108
- 249,
109
- 2,
110
- 127,
111
- 80,
112
- 60,
113
- 159,
114
- 168,
115
- 81,
116
- 163,
117
- 64,
118
- 143,
119
- 146,
120
- 157,
121
- 56,
122
- 245,
123
- 188,
124
- 182,
125
- 218,
126
- 33,
127
- 16,
128
- 255,
129
- 243,
130
- 210,
131
- 205,
132
- 12,
133
- 19,
134
- 236,
135
- 95,
136
- 151,
137
- 68,
138
- 23,
139
- 196,
140
- 167,
141
- 126,
142
- 61,
143
- 100,
144
- 93,
145
- 25,
146
- 115,
147
- 96,
148
- 129,
149
- 79,
150
- 220,
151
- 34,
152
- 42,
153
- 144,
154
- 136,
155
- 70,
156
- 238,
157
- 184,
158
- 20,
159
- 222,
160
- 94,
161
- 11,
162
- 219,
163
- 224,
164
- 50,
165
- 58,
166
- 10,
167
- 73,
168
- 6,
169
- 36,
170
- 92,
171
- 194,
172
- 211,
173
- 172,
174
- 98,
175
- 145,
176
- 149,
177
- 228,
178
- 121,
179
- 231,
180
- 200,
181
- 55,
182
- 109,
183
- 141,
184
- 213,
185
- 78,
186
- 169,
187
- 108,
188
- 86,
189
- 244,
190
- 234,
191
- 101,
192
- 122,
193
- 174,
194
- 8,
195
- 186,
196
- 120,
197
- 37,
198
- 46,
199
- 28,
200
- 166,
201
- 180,
202
- 198,
203
- 232,
204
- 221,
205
- 116,
206
- 31,
207
- 75,
208
- 189,
209
- 139,
210
- 138,
211
- 112,
212
- 62,
213
- 181,
214
- 102,
215
- 72,
216
- 3,
217
- 246,
218
- 14,
219
- 97,
220
- 53,
221
- 87,
222
- 185,
223
- 134,
224
- 193,
225
- 29,
226
- 158,
227
- 225,
228
- 248,
229
- 152,
230
- 17,
231
- 105,
232
- 217,
233
- 142,
234
- 148,
235
- 155,
236
- 30,
237
- 135,
238
- 233,
239
- 206,
240
- 85,
241
- 40,
242
- 223,
243
- 140,
244
- 161,
245
- 137,
246
- 13,
247
- 191,
248
- 230,
249
- 66,
250
- 104,
251
- 65,
252
- 153,
253
- 45,
254
- 15,
255
- 176,
256
- 84,
257
- 187,
258
- 22
5
+ 99,
6
+ 124,
7
+ 119,
8
+ 123,
9
+ 242,
10
+ 107,
11
+ 111,
12
+ 197,
13
+ 48,
14
+ 1,
15
+ 103,
16
+ 43,
17
+ 254,
18
+ 215,
19
+ 171,
20
+ 118,
21
+ 202,
22
+ 130,
23
+ 201,
24
+ 125,
25
+ 250,
26
+ 89,
27
+ 71,
28
+ 240,
29
+ 173,
30
+ 212,
31
+ 162,
32
+ 175,
33
+ 156,
34
+ 164,
35
+ 114,
36
+ 192,
37
+ 183,
38
+ 253,
39
+ 147,
40
+ 38,
41
+ 54,
42
+ 63,
43
+ 247,
44
+ 204,
45
+ 52,
46
+ 165,
47
+ 229,
48
+ 241,
49
+ 113,
50
+ 216,
51
+ 49,
52
+ 21,
53
+ 4,
54
+ 199,
55
+ 35,
56
+ 195,
57
+ 24,
58
+ 150,
59
+ 5,
60
+ 154,
61
+ 7,
62
+ 18,
63
+ 128,
64
+ 226,
65
+ 235,
66
+ 39,
67
+ 178,
68
+ 117,
69
+ 9,
70
+ 131,
71
+ 44,
72
+ 26,
73
+ 27,
74
+ 110,
75
+ 90,
76
+ 160,
77
+ 82,
78
+ 59,
79
+ 214,
80
+ 179,
81
+ 41,
82
+ 227,
83
+ 47,
84
+ 132,
85
+ 83,
86
+ 209,
87
+ 0,
88
+ 237,
89
+ 32,
90
+ 252,
91
+ 177,
92
+ 91,
93
+ 106,
94
+ 203,
95
+ 190,
96
+ 57,
97
+ 74,
98
+ 76,
99
+ 88,
100
+ 207,
101
+ 208,
102
+ 239,
103
+ 170,
104
+ 251,
105
+ 67,
106
+ 77,
107
+ 51,
108
+ 133,
109
+ 69,
110
+ 249,
111
+ 2,
112
+ 127,
113
+ 80,
114
+ 60,
115
+ 159,
116
+ 168,
117
+ 81,
118
+ 163,
119
+ 64,
120
+ 143,
121
+ 146,
122
+ 157,
123
+ 56,
124
+ 245,
125
+ 188,
126
+ 182,
127
+ 218,
128
+ 33,
129
+ 16,
130
+ 255,
131
+ 243,
132
+ 210,
133
+ 205,
134
+ 12,
135
+ 19,
136
+ 236,
137
+ 95,
138
+ 151,
139
+ 68,
140
+ 23,
141
+ 196,
142
+ 167,
143
+ 126,
144
+ 61,
145
+ 100,
146
+ 93,
147
+ 25,
148
+ 115,
149
+ 96,
150
+ 129,
151
+ 79,
152
+ 220,
153
+ 34,
154
+ 42,
155
+ 144,
156
+ 136,
157
+ 70,
158
+ 238,
159
+ 184,
160
+ 20,
161
+ 222,
162
+ 94,
163
+ 11,
164
+ 219,
165
+ 224,
166
+ 50,
167
+ 58,
168
+ 10,
169
+ 73,
170
+ 6,
171
+ 36,
172
+ 92,
173
+ 194,
174
+ 211,
175
+ 172,
176
+ 98,
177
+ 145,
178
+ 149,
179
+ 228,
180
+ 121,
181
+ 231,
182
+ 200,
183
+ 55,
184
+ 109,
185
+ 141,
186
+ 213,
187
+ 78,
188
+ 169,
189
+ 108,
190
+ 86,
191
+ 244,
192
+ 234,
193
+ 101,
194
+ 122,
195
+ 174,
196
+ 8,
197
+ 186,
198
+ 120,
199
+ 37,
200
+ 46,
201
+ 28,
202
+ 166,
203
+ 180,
204
+ 198,
205
+ 232,
206
+ 221,
207
+ 116,
208
+ 31,
209
+ 75,
210
+ 189,
211
+ 139,
212
+ 138,
213
+ 112,
214
+ 62,
215
+ 181,
216
+ 102,
217
+ 72,
218
+ 3,
219
+ 246,
220
+ 14,
221
+ 97,
222
+ 53,
223
+ 87,
224
+ 185,
225
+ 134,
226
+ 193,
227
+ 29,
228
+ 158,
229
+ 225,
230
+ 248,
231
+ 152,
232
+ 17,
233
+ 105,
234
+ 217,
235
+ 142,
236
+ 148,
237
+ 155,
238
+ 30,
239
+ 135,
240
+ 233,
241
+ 206,
242
+ 85,
243
+ 40,
244
+ 223,
245
+ 140,
246
+ 161,
247
+ 137,
248
+ 13,
249
+ 191,
250
+ 230,
251
+ 66,
252
+ 104,
253
+ 65,
254
+ 153,
255
+ 45,
256
+ 15,
257
+ 176,
258
+ 84,
259
+ 187,
260
+ 22
259
261
  ]);
260
262
  const INV_SBOX = new Uint8Array([
261
- 82,
262
- 9,
263
- 106,
264
- 213,
265
- 48,
266
- 54,
267
- 165,
268
- 56,
269
- 191,
270
- 64,
271
- 163,
272
- 158,
273
- 129,
274
- 243,
275
- 215,
276
- 251,
277
- 124,
278
- 227,
279
- 57,
280
- 130,
281
- 155,
282
- 47,
283
- 255,
284
- 135,
285
- 52,
286
- 142,
287
- 67,
288
- 68,
289
- 196,
290
- 222,
291
- 233,
292
- 203,
293
- 84,
294
- 123,
295
- 148,
296
- 50,
297
- 166,
298
- 194,
299
- 35,
300
- 61,
301
- 238,
302
- 76,
303
- 149,
304
- 11,
305
- 66,
306
- 250,
307
- 195,
308
- 78,
309
- 8,
310
- 46,
311
- 161,
312
- 102,
313
- 40,
314
- 217,
315
- 36,
316
- 178,
317
- 118,
318
- 91,
319
- 162,
320
- 73,
321
- 109,
322
- 139,
323
- 209,
324
- 37,
325
- 114,
326
- 248,
327
- 246,
328
- 100,
329
- 134,
330
- 104,
331
- 152,
332
- 22,
333
- 212,
334
- 164,
335
- 92,
336
- 204,
337
- 93,
338
- 101,
339
- 182,
340
- 146,
341
- 108,
342
- 112,
343
- 72,
344
- 80,
345
- 253,
346
- 237,
347
- 185,
348
- 218,
349
- 94,
350
- 21,
351
- 70,
352
- 87,
353
- 167,
354
- 141,
355
- 157,
356
- 132,
357
- 144,
358
- 216,
359
- 171,
360
- 0,
361
- 140,
362
- 188,
363
- 211,
364
- 10,
365
- 247,
366
- 228,
367
- 88,
368
- 5,
369
- 184,
370
- 179,
371
- 69,
372
- 6,
373
- 208,
374
- 44,
375
- 30,
376
- 143,
377
- 202,
378
- 63,
379
- 15,
380
- 2,
381
- 193,
382
- 175,
383
- 189,
384
- 3,
385
- 1,
386
- 19,
387
- 138,
388
- 107,
389
- 58,
390
- 145,
391
- 17,
392
- 65,
393
- 79,
394
- 103,
395
- 220,
396
- 234,
397
- 151,
398
- 242,
399
- 207,
400
- 206,
401
- 240,
402
- 180,
403
- 230,
404
- 115,
405
- 150,
406
- 172,
407
- 116,
408
- 34,
409
- 231,
410
- 173,
411
- 53,
412
- 133,
413
- 226,
414
- 249,
415
- 55,
416
- 232,
417
- 28,
418
- 117,
419
- 223,
420
- 110,
421
- 71,
422
- 241,
423
- 26,
424
- 113,
425
- 29,
426
- 41,
427
- 197,
428
- 137,
429
- 111,
430
- 183,
431
- 98,
432
- 14,
433
- 170,
434
- 24,
435
- 190,
436
- 27,
437
- 252,
438
- 86,
439
- 62,
440
- 75,
441
- 198,
442
- 210,
443
- 121,
444
- 32,
445
- 154,
446
- 219,
447
- 192,
448
- 254,
449
- 120,
450
- 205,
451
- 90,
452
- 244,
453
- 31,
454
- 221,
455
- 168,
456
- 51,
457
- 136,
458
- 7,
459
- 199,
460
- 49,
461
- 177,
462
- 18,
463
- 16,
464
- 89,
465
- 39,
466
- 128,
467
- 236,
468
- 95,
469
- 96,
470
- 81,
471
- 127,
472
- 169,
473
- 25,
474
- 181,
475
- 74,
476
- 13,
477
- 45,
478
- 229,
479
- 122,
480
- 159,
481
- 147,
482
- 201,
483
- 156,
484
- 239,
485
- 160,
486
- 224,
487
- 59,
488
- 77,
489
- 174,
490
- 42,
491
- 245,
492
- 176,
493
- 200,
494
- 235,
495
- 187,
496
- 60,
497
- 131,
498
- 83,
499
- 153,
500
- 97,
501
- 23,
502
- 43,
503
- 4,
504
- 126,
505
- 186,
506
- 119,
507
- 214,
508
- 38,
509
- 225,
510
- 105,
511
- 20,
512
- 99,
513
- 85,
514
- 33,
515
- 12,
516
- 125
263
+ 82,
264
+ 9,
265
+ 106,
266
+ 213,
267
+ 48,
268
+ 54,
269
+ 165,
270
+ 56,
271
+ 191,
272
+ 64,
273
+ 163,
274
+ 158,
275
+ 129,
276
+ 243,
277
+ 215,
278
+ 251,
279
+ 124,
280
+ 227,
281
+ 57,
282
+ 130,
283
+ 155,
284
+ 47,
285
+ 255,
286
+ 135,
287
+ 52,
288
+ 142,
289
+ 67,
290
+ 68,
291
+ 196,
292
+ 222,
293
+ 233,
294
+ 203,
295
+ 84,
296
+ 123,
297
+ 148,
298
+ 50,
299
+ 166,
300
+ 194,
301
+ 35,
302
+ 61,
303
+ 238,
304
+ 76,
305
+ 149,
306
+ 11,
307
+ 66,
308
+ 250,
309
+ 195,
310
+ 78,
311
+ 8,
312
+ 46,
313
+ 161,
314
+ 102,
315
+ 40,
316
+ 217,
317
+ 36,
318
+ 178,
319
+ 118,
320
+ 91,
321
+ 162,
322
+ 73,
323
+ 109,
324
+ 139,
325
+ 209,
326
+ 37,
327
+ 114,
328
+ 248,
329
+ 246,
330
+ 100,
331
+ 134,
332
+ 104,
333
+ 152,
334
+ 22,
335
+ 212,
336
+ 164,
337
+ 92,
338
+ 204,
339
+ 93,
340
+ 101,
341
+ 182,
342
+ 146,
343
+ 108,
344
+ 112,
345
+ 72,
346
+ 80,
347
+ 253,
348
+ 237,
349
+ 185,
350
+ 218,
351
+ 94,
352
+ 21,
353
+ 70,
354
+ 87,
355
+ 167,
356
+ 141,
357
+ 157,
358
+ 132,
359
+ 144,
360
+ 216,
361
+ 171,
362
+ 0,
363
+ 140,
364
+ 188,
365
+ 211,
366
+ 10,
367
+ 247,
368
+ 228,
369
+ 88,
370
+ 5,
371
+ 184,
372
+ 179,
373
+ 69,
374
+ 6,
375
+ 208,
376
+ 44,
377
+ 30,
378
+ 143,
379
+ 202,
380
+ 63,
381
+ 15,
382
+ 2,
383
+ 193,
384
+ 175,
385
+ 189,
386
+ 3,
387
+ 1,
388
+ 19,
389
+ 138,
390
+ 107,
391
+ 58,
392
+ 145,
393
+ 17,
394
+ 65,
395
+ 79,
396
+ 103,
397
+ 220,
398
+ 234,
399
+ 151,
400
+ 242,
401
+ 207,
402
+ 206,
403
+ 240,
404
+ 180,
405
+ 230,
406
+ 115,
407
+ 150,
408
+ 172,
409
+ 116,
410
+ 34,
411
+ 231,
412
+ 173,
413
+ 53,
414
+ 133,
415
+ 226,
416
+ 249,
417
+ 55,
418
+ 232,
419
+ 28,
420
+ 117,
421
+ 223,
422
+ 110,
423
+ 71,
424
+ 241,
425
+ 26,
426
+ 113,
427
+ 29,
428
+ 41,
429
+ 197,
430
+ 137,
431
+ 111,
432
+ 183,
433
+ 98,
434
+ 14,
435
+ 170,
436
+ 24,
437
+ 190,
438
+ 27,
439
+ 252,
440
+ 86,
441
+ 62,
442
+ 75,
443
+ 198,
444
+ 210,
445
+ 121,
446
+ 32,
447
+ 154,
448
+ 219,
449
+ 192,
450
+ 254,
451
+ 120,
452
+ 205,
453
+ 90,
454
+ 244,
455
+ 31,
456
+ 221,
457
+ 168,
458
+ 51,
459
+ 136,
460
+ 7,
461
+ 199,
462
+ 49,
463
+ 177,
464
+ 18,
465
+ 16,
466
+ 89,
467
+ 39,
468
+ 128,
469
+ 236,
470
+ 95,
471
+ 96,
472
+ 81,
473
+ 127,
474
+ 169,
475
+ 25,
476
+ 181,
477
+ 74,
478
+ 13,
479
+ 45,
480
+ 229,
481
+ 122,
482
+ 159,
483
+ 147,
484
+ 201,
485
+ 156,
486
+ 239,
487
+ 160,
488
+ 224,
489
+ 59,
490
+ 77,
491
+ 174,
492
+ 42,
493
+ 245,
494
+ 176,
495
+ 200,
496
+ 235,
497
+ 187,
498
+ 60,
499
+ 131,
500
+ 83,
501
+ 153,
502
+ 97,
503
+ 23,
504
+ 43,
505
+ 4,
506
+ 126,
507
+ 186,
508
+ 119,
509
+ 214,
510
+ 38,
511
+ 225,
512
+ 105,
513
+ 20,
514
+ 99,
515
+ 85,
516
+ 33,
517
+ 12,
518
+ 125
517
519
  ]);
518
- const RCON = [1, 2, 4, 8, 16, 32, 64, 128, 27, 54];
520
+ const RCON = [
521
+ 1,
522
+ 2,
523
+ 4,
524
+ 8,
525
+ 16,
526
+ 32,
527
+ 64,
528
+ 128,
529
+ 27,
530
+ 54
531
+ ];
519
532
  function gmul(a, b) {
520
- let p = 0;
521
- for (let i = 0; i < 8; i++) {
522
- if (b & 1) p ^= a;
523
- const hi = a & 128;
524
- a = a << 1 & 255;
525
- if (hi) a ^= 27;
526
- b >>= 1;
527
- }
528
- return p;
533
+ let p = 0;
534
+ for (let i = 0; i < 8; i++) {
535
+ if (b & 1) p ^= a;
536
+ const hi = a & 128;
537
+ a = a << 1 & 255;
538
+ if (hi) a ^= 27;
539
+ b >>= 1;
540
+ }
541
+ return p;
529
542
  }
530
543
  function keyExpansion(key) {
531
- const nk = key.length / 4;
532
- const nr = nk + 6;
533
- const nw = 4 * (nr + 1);
534
- const w = new Array(nw);
535
- for (let i = 0; i < nk; i++) {
536
- w[i] = new Uint8Array([key[4 * i], key[4 * i + 1], key[4 * i + 2], key[4 * i + 3]]);
537
- }
538
- for (let i = nk; i < nw; i++) {
539
- let temp = new Uint8Array(w[i - 1]);
540
- if (i % nk === 0) {
541
- temp = new Uint8Array([
542
- SBOX[temp[1]] ^ RCON[i / nk - 1],
543
- SBOX[temp[2]],
544
- SBOX[temp[3]],
545
- SBOX[temp[0]]
546
- ]);
547
- } else if (nk > 6 && i % nk === 4) {
548
- temp = new Uint8Array([SBOX[temp[0]], SBOX[temp[1]], SBOX[temp[2]], SBOX[temp[3]]]);
549
- }
550
- w[i] = new Uint8Array(4);
551
- for (let j = 0; j < 4; j++) w[i][j] = w[i - nk][j] ^ temp[j];
552
- }
553
- const roundKeys = [];
554
- for (let r = 0; r <= nr; r++) {
555
- const rk = new Uint8Array(16);
556
- for (let c = 0; c < 4; c++) {
557
- rk[4 * c] = w[4 * r + c][0];
558
- rk[4 * c + 1] = w[4 * r + c][1];
559
- rk[4 * c + 2] = w[4 * r + c][2];
560
- rk[4 * c + 3] = w[4 * r + c][3];
561
- }
562
- roundKeys.push(rk);
563
- }
564
- return roundKeys;
544
+ const nk = key.length / 4;
545
+ const nr = nk + 6;
546
+ const nw = 4 * (nr + 1);
547
+ const w = new Array(nw);
548
+ for (let i = 0; i < nk; i++) {
549
+ w[i] = new Uint8Array([
550
+ key[4 * i],
551
+ key[4 * i + 1],
552
+ key[4 * i + 2],
553
+ key[4 * i + 3]
554
+ ]);
555
+ }
556
+ for (let i = nk; i < nw; i++) {
557
+ let temp = new Uint8Array(w[i - 1]);
558
+ if (i % nk === 0) {
559
+ temp = new Uint8Array([
560
+ SBOX[temp[1]] ^ RCON[i / nk - 1],
561
+ SBOX[temp[2]],
562
+ SBOX[temp[3]],
563
+ SBOX[temp[0]]
564
+ ]);
565
+ } else if (nk > 6 && i % nk === 4) {
566
+ temp = new Uint8Array([
567
+ SBOX[temp[0]],
568
+ SBOX[temp[1]],
569
+ SBOX[temp[2]],
570
+ SBOX[temp[3]]
571
+ ]);
572
+ }
573
+ w[i] = new Uint8Array(4);
574
+ for (let j = 0; j < 4; j++) w[i][j] = w[i - nk][j] ^ temp[j];
575
+ }
576
+ const roundKeys = [];
577
+ for (let r = 0; r <= nr; r++) {
578
+ const rk = new Uint8Array(16);
579
+ for (let c = 0; c < 4; c++) {
580
+ rk[4 * c] = w[4 * r + c][0];
581
+ rk[4 * c + 1] = w[4 * r + c][1];
582
+ rk[4 * c + 2] = w[4 * r + c][2];
583
+ rk[4 * c + 3] = w[4 * r + c][3];
584
+ }
585
+ roundKeys.push(rk);
586
+ }
587
+ return roundKeys;
565
588
  }
566
589
  function aesEncryptBlock(block, roundKeys) {
567
- const state = new Uint8Array(block);
568
- const nr = roundKeys.length - 1;
569
- for (let i = 0; i < 16; i++) state[i] ^= roundKeys[0][i];
570
- for (let round = 1; round < nr; round++) {
571
- for (let i = 0; i < 16; i++) state[i] = SBOX[state[i]];
572
- const t1 = state[1];
573
- state[1] = state[5];
574
- state[5] = state[9];
575
- state[9] = state[13];
576
- state[13] = t1;
577
- const t2a = state[2];
578
- const t2b = state[6];
579
- state[2] = state[10];
580
- state[6] = state[14];
581
- state[10] = t2a;
582
- state[14] = t2b;
583
- const t3 = state[15];
584
- state[15] = state[11];
585
- state[11] = state[7];
586
- state[7] = state[3];
587
- state[3] = t3;
588
- for (let c = 0; c < 4; c++) {
589
- const i = c * 4;
590
- const a0 = state[i], a1 = state[i + 1], a2 = state[i + 2], a3 = state[i + 3];
591
- state[i] = gmul(2, a0) ^ gmul(3, a1) ^ a2 ^ a3;
592
- state[i + 1] = a0 ^ gmul(2, a1) ^ gmul(3, a2) ^ a3;
593
- state[i + 2] = a0 ^ a1 ^ gmul(2, a2) ^ gmul(3, a3);
594
- state[i + 3] = gmul(3, a0) ^ a1 ^ a2 ^ gmul(2, a3);
595
- }
596
- for (let i = 0; i < 16; i++) state[i] ^= roundKeys[round][i];
597
- }
598
- for (let i = 0; i < 16; i++) state[i] = SBOX[state[i]];
599
- const t1f = state[1];
600
- state[1] = state[5];
601
- state[5] = state[9];
602
- state[9] = state[13];
603
- state[13] = t1f;
604
- const t2af = state[2];
605
- const t2bf = state[6];
606
- state[2] = state[10];
607
- state[6] = state[14];
608
- state[10] = t2af;
609
- state[14] = t2bf;
610
- const t3f = state[15];
611
- state[15] = state[11];
612
- state[11] = state[7];
613
- state[7] = state[3];
614
- state[3] = t3f;
615
- for (let i = 0; i < 16; i++) state[i] ^= roundKeys[nr][i];
616
- return state;
590
+ const state = new Uint8Array(block);
591
+ const nr = roundKeys.length - 1;
592
+ for (let i = 0; i < 16; i++) state[i] ^= roundKeys[0][i];
593
+ for (let round = 1; round < nr; round++) {
594
+ for (let i = 0; i < 16; i++) state[i] = SBOX[state[i]];
595
+ const t1 = state[1];
596
+ state[1] = state[5];
597
+ state[5] = state[9];
598
+ state[9] = state[13];
599
+ state[13] = t1;
600
+ const t2a = state[2];
601
+ const t2b = state[6];
602
+ state[2] = state[10];
603
+ state[6] = state[14];
604
+ state[10] = t2a;
605
+ state[14] = t2b;
606
+ const t3 = state[15];
607
+ state[15] = state[11];
608
+ state[11] = state[7];
609
+ state[7] = state[3];
610
+ state[3] = t3;
611
+ for (let c = 0; c < 4; c++) {
612
+ const i = c * 4;
613
+ const a0 = state[i], a1 = state[i + 1], a2 = state[i + 2], a3 = state[i + 3];
614
+ state[i] = gmul(2, a0) ^ gmul(3, a1) ^ a2 ^ a3;
615
+ state[i + 1] = a0 ^ gmul(2, a1) ^ gmul(3, a2) ^ a3;
616
+ state[i + 2] = a0 ^ a1 ^ gmul(2, a2) ^ gmul(3, a3);
617
+ state[i + 3] = gmul(3, a0) ^ a1 ^ a2 ^ gmul(2, a3);
618
+ }
619
+ for (let i = 0; i < 16; i++) state[i] ^= roundKeys[round][i];
620
+ }
621
+ for (let i = 0; i < 16; i++) state[i] = SBOX[state[i]];
622
+ const t1f = state[1];
623
+ state[1] = state[5];
624
+ state[5] = state[9];
625
+ state[9] = state[13];
626
+ state[13] = t1f;
627
+ const t2af = state[2];
628
+ const t2bf = state[6];
629
+ state[2] = state[10];
630
+ state[6] = state[14];
631
+ state[10] = t2af;
632
+ state[14] = t2bf;
633
+ const t3f = state[15];
634
+ state[15] = state[11];
635
+ state[11] = state[7];
636
+ state[7] = state[3];
637
+ state[3] = t3f;
638
+ for (let i = 0; i < 16; i++) state[i] ^= roundKeys[nr][i];
639
+ return state;
617
640
  }
618
641
  function aesDecryptBlock(block, roundKeys) {
619
- const state = new Uint8Array(block);
620
- const nr = roundKeys.length - 1;
621
- for (let i = 0; i < 16; i++) state[i] ^= roundKeys[nr][i];
622
- for (let round = nr - 1; round > 0; round--) {
623
- const t1 = state[13];
624
- state[13] = state[9];
625
- state[9] = state[5];
626
- state[5] = state[1];
627
- state[1] = t1;
628
- const t2a = state[10];
629
- const t2b = state[14];
630
- state[10] = state[2];
631
- state[14] = state[6];
632
- state[2] = t2a;
633
- state[6] = t2b;
634
- const t3 = state[3];
635
- state[3] = state[7];
636
- state[7] = state[11];
637
- state[11] = state[15];
638
- state[15] = t3;
639
- for (let i = 0; i < 16; i++) state[i] = INV_SBOX[state[i]];
640
- for (let i = 0; i < 16; i++) state[i] ^= roundKeys[round][i];
641
- for (let c = 0; c < 4; c++) {
642
- const i = c * 4;
643
- const a0 = state[i], a1 = state[i + 1], a2 = state[i + 2], a3 = state[i + 3];
644
- state[i] = gmul(14, a0) ^ gmul(11, a1) ^ gmul(13, a2) ^ gmul(9, a3);
645
- state[i + 1] = gmul(9, a0) ^ gmul(14, a1) ^ gmul(11, a2) ^ gmul(13, a3);
646
- state[i + 2] = gmul(13, a0) ^ gmul(9, a1) ^ gmul(14, a2) ^ gmul(11, a3);
647
- state[i + 3] = gmul(11, a0) ^ gmul(13, a1) ^ gmul(9, a2) ^ gmul(14, a3);
648
- }
649
- }
650
- const t1f = state[13];
651
- state[13] = state[9];
652
- state[9] = state[5];
653
- state[5] = state[1];
654
- state[1] = t1f;
655
- const t2af = state[10];
656
- const t2bf = state[14];
657
- state[10] = state[2];
658
- state[14] = state[6];
659
- state[2] = t2af;
660
- state[6] = t2bf;
661
- const t3f = state[3];
662
- state[3] = state[7];
663
- state[7] = state[11];
664
- state[11] = state[15];
665
- state[15] = t3f;
666
- for (let i = 0; i < 16; i++) state[i] = INV_SBOX[state[i]];
667
- for (let i = 0; i < 16; i++) state[i] ^= roundKeys[0][i];
668
- return state;
642
+ const state = new Uint8Array(block);
643
+ const nr = roundKeys.length - 1;
644
+ for (let i = 0; i < 16; i++) state[i] ^= roundKeys[nr][i];
645
+ for (let round = nr - 1; round > 0; round--) {
646
+ const t1 = state[13];
647
+ state[13] = state[9];
648
+ state[9] = state[5];
649
+ state[5] = state[1];
650
+ state[1] = t1;
651
+ const t2a = state[10];
652
+ const t2b = state[14];
653
+ state[10] = state[2];
654
+ state[14] = state[6];
655
+ state[2] = t2a;
656
+ state[6] = t2b;
657
+ const t3 = state[3];
658
+ state[3] = state[7];
659
+ state[7] = state[11];
660
+ state[11] = state[15];
661
+ state[15] = t3;
662
+ for (let i = 0; i < 16; i++) state[i] = INV_SBOX[state[i]];
663
+ for (let i = 0; i < 16; i++) state[i] ^= roundKeys[round][i];
664
+ for (let c = 0; c < 4; c++) {
665
+ const i = c * 4;
666
+ const a0 = state[i], a1 = state[i + 1], a2 = state[i + 2], a3 = state[i + 3];
667
+ state[i] = gmul(14, a0) ^ gmul(11, a1) ^ gmul(13, a2) ^ gmul(9, a3);
668
+ state[i + 1] = gmul(9, a0) ^ gmul(14, a1) ^ gmul(11, a2) ^ gmul(13, a3);
669
+ state[i + 2] = gmul(13, a0) ^ gmul(9, a1) ^ gmul(14, a2) ^ gmul(11, a3);
670
+ state[i + 3] = gmul(11, a0) ^ gmul(13, a1) ^ gmul(9, a2) ^ gmul(14, a3);
671
+ }
672
+ }
673
+ const t1f = state[13];
674
+ state[13] = state[9];
675
+ state[9] = state[5];
676
+ state[5] = state[1];
677
+ state[1] = t1f;
678
+ const t2af = state[10];
679
+ const t2bf = state[14];
680
+ state[10] = state[2];
681
+ state[14] = state[6];
682
+ state[2] = t2af;
683
+ state[6] = t2bf;
684
+ const t3f = state[3];
685
+ state[3] = state[7];
686
+ state[7] = state[11];
687
+ state[11] = state[15];
688
+ state[15] = t3f;
689
+ for (let i = 0; i < 16; i++) state[i] = INV_SBOX[state[i]];
690
+ for (let i = 0; i < 16; i++) state[i] ^= roundKeys[0][i];
691
+ return state;
669
692
  }
670
693
  function incrementCounter(counter) {
671
- for (let i = 15; i >= 0; i--) {
672
- if (++counter[i] !== 0) break;
673
- }
694
+ for (let i = 15; i >= 0; i--) {
695
+ if (++counter[i] !== 0) break;
696
+ }
674
697
  }
675
698
  function gcmIncrementCounter(counter) {
676
- for (let i = 15; i >= 12; i--) {
677
- if (++counter[i] !== 0) break;
678
- }
699
+ for (let i = 15; i >= 12; i--) {
700
+ if (++counter[i] !== 0) break;
701
+ }
679
702
  }
703
+ /**
704
+ * Multiply two 128-bit values in GF(2^128) using the irreducible polynomial
705
+ * x^128 + x^7 + x^2 + x + 1 (represented as R = 0xe1 << 120).
706
+ *
707
+ * X and Y are 16-byte Uint8Arrays (big-endian bit ordering).
708
+ * Returns a new 16-byte Uint8Array.
709
+ */
680
710
  function gfMul(X, Y) {
681
- const Z = new Uint8Array(16);
682
- const V = new Uint8Array(X);
683
- for (let i = 0; i < 128; i++) {
684
- if (Y[i >>> 3] & 1 << 7 - (i & 7)) {
685
- for (let j = 0; j < 16; j++) Z[j] ^= V[j];
686
- }
687
- const lsb = V[15] & 1;
688
- for (let j = 15; j > 0; j--) {
689
- V[j] = V[j] >>> 1 | (V[j - 1] & 1) << 7;
690
- }
691
- V[0] = V[0] >>> 1;
692
- if (lsb) {
693
- V[0] ^= 225;
694
- }
695
- }
696
- return Z;
711
+ const Z = new Uint8Array(16);
712
+ const V = new Uint8Array(X);
713
+ for (let i = 0; i < 128; i++) {
714
+ if (Y[i >>> 3] & 1 << 7 - (i & 7)) {
715
+ for (let j = 0; j < 16; j++) Z[j] ^= V[j];
716
+ }
717
+ const lsb = V[15] & 1;
718
+ for (let j = 15; j > 0; j--) {
719
+ V[j] = V[j] >>> 1 | (V[j - 1] & 1) << 7;
720
+ }
721
+ V[0] = V[0] >>> 1;
722
+ if (lsb) {
723
+ V[0] ^= 225;
724
+ }
725
+ }
726
+ return Z;
697
727
  }
728
+ /**
729
+ * GHASH function per NIST SP 800-38D.
730
+ *
731
+ * H: the hash subkey (AES_K(0^128)), 16 bytes
732
+ * aad: additional authenticated data (arbitrary length)
733
+ * ciphertext: ciphertext (arbitrary length)
734
+ *
735
+ * Returns a 16-byte authentication hash.
736
+ */
698
737
  function ghash(H, aad, ciphertext) {
699
- const X = new Uint8Array(16);
700
- const aadBlocks = Math.ceil(aad.length / 16) || 0;
701
- for (let i = 0; i < aadBlocks; i++) {
702
- const start = i * 16;
703
- const end = Math.min(start + 16, aad.length);
704
- for (let j = 0; j < 16; j++) {
705
- const idx = start + j;
706
- if (idx < end) {
707
- X[j] ^= aad[idx];
708
- }
709
- }
710
- const product2 = gfMul(X, H);
711
- X.set(product2);
712
- }
713
- const ctBlocks = Math.ceil(ciphertext.length / 16) || 0;
714
- for (let i = 0; i < ctBlocks; i++) {
715
- const start = i * 16;
716
- const end = Math.min(start + 16, ciphertext.length);
717
- for (let j = 0; j < 16; j++) {
718
- const idx = start + j;
719
- if (idx < end) {
720
- X[j] ^= ciphertext[idx];
721
- }
722
- }
723
- const product2 = gfMul(X, H);
724
- X.set(product2);
725
- }
726
- const lenBlock = new Uint8Array(16);
727
- const aadBits = aad.length * 8;
728
- const ctBits = ciphertext.length * 8;
729
- const aadHi = Math.floor(aadBits / 4294967296);
730
- const aadLo = aadBits >>> 0;
731
- lenBlock[0] = aadHi >>> 24 & 255;
732
- lenBlock[1] = aadHi >>> 16 & 255;
733
- lenBlock[2] = aadHi >>> 8 & 255;
734
- lenBlock[3] = aadHi & 255;
735
- lenBlock[4] = aadLo >>> 24 & 255;
736
- lenBlock[5] = aadLo >>> 16 & 255;
737
- lenBlock[6] = aadLo >>> 8 & 255;
738
- lenBlock[7] = aadLo & 255;
739
- const ctHi = Math.floor(ctBits / 4294967296);
740
- const ctLo = ctBits >>> 0;
741
- lenBlock[8] = ctHi >>> 24 & 255;
742
- lenBlock[9] = ctHi >>> 16 & 255;
743
- lenBlock[10] = ctHi >>> 8 & 255;
744
- lenBlock[11] = ctHi & 255;
745
- lenBlock[12] = ctLo >>> 24 & 255;
746
- lenBlock[13] = ctLo >>> 16 & 255;
747
- lenBlock[14] = ctLo >>> 8 & 255;
748
- lenBlock[15] = ctLo & 255;
749
- for (let j = 0; j < 16; j++) X[j] ^= lenBlock[j];
750
- const product = gfMul(X, H);
751
- X.set(product);
752
- return X;
738
+ const X = new Uint8Array(16);
739
+ const aadBlocks = Math.ceil(aad.length / 16) || 0;
740
+ for (let i = 0; i < aadBlocks; i++) {
741
+ const start = i * 16;
742
+ const end = Math.min(start + 16, aad.length);
743
+ for (let j = 0; j < 16; j++) {
744
+ const idx = start + j;
745
+ if (idx < end) {
746
+ X[j] ^= aad[idx];
747
+ }
748
+ }
749
+ const product = gfMul(X, H);
750
+ X.set(product);
751
+ }
752
+ const ctBlocks = Math.ceil(ciphertext.length / 16) || 0;
753
+ for (let i = 0; i < ctBlocks; i++) {
754
+ const start = i * 16;
755
+ const end = Math.min(start + 16, ciphertext.length);
756
+ for (let j = 0; j < 16; j++) {
757
+ const idx = start + j;
758
+ if (idx < end) {
759
+ X[j] ^= ciphertext[idx];
760
+ }
761
+ }
762
+ const product = gfMul(X, H);
763
+ X.set(product);
764
+ }
765
+ const lenBlock = new Uint8Array(16);
766
+ const aadBits = aad.length * 8;
767
+ const ctBits = ciphertext.length * 8;
768
+ const aadHi = Math.floor(aadBits / 4294967296);
769
+ const aadLo = aadBits >>> 0;
770
+ lenBlock[0] = aadHi >>> 24 & 255;
771
+ lenBlock[1] = aadHi >>> 16 & 255;
772
+ lenBlock[2] = aadHi >>> 8 & 255;
773
+ lenBlock[3] = aadHi & 255;
774
+ lenBlock[4] = aadLo >>> 24 & 255;
775
+ lenBlock[5] = aadLo >>> 16 & 255;
776
+ lenBlock[6] = aadLo >>> 8 & 255;
777
+ lenBlock[7] = aadLo & 255;
778
+ const ctHi = Math.floor(ctBits / 4294967296);
779
+ const ctLo = ctBits >>> 0;
780
+ lenBlock[8] = ctHi >>> 24 & 255;
781
+ lenBlock[9] = ctHi >>> 16 & 255;
782
+ lenBlock[10] = ctHi >>> 8 & 255;
783
+ lenBlock[11] = ctHi & 255;
784
+ lenBlock[12] = ctLo >>> 24 & 255;
785
+ lenBlock[13] = ctLo >>> 16 & 255;
786
+ lenBlock[14] = ctLo >>> 8 & 255;
787
+ lenBlock[15] = ctLo & 255;
788
+ for (let j = 0; j < 16; j++) X[j] ^= lenBlock[j];
789
+ const product = gfMul(X, H);
790
+ X.set(product);
791
+ return X;
753
792
  }
754
793
  function parseAlgorithm(algorithm) {
755
- const lower = algorithm.toLowerCase();
756
- const match = lower.match(/^aes-(128|192|256)-(cbc|ctr|ecb|cfb|ofb|gcm)$/);
757
- if (!match) {
758
- throw new Error(`Unsupported cipher algorithm: ${algorithm}`);
759
- }
760
- const keyBits = parseInt(match[1]);
761
- const mode = match[2];
762
- return {
763
- keySize: keyBits / 8,
764
- ivSize: mode === "ecb" ? 0 : mode === "gcm" ? 12 : 16,
765
- mode
766
- };
794
+ const lower = algorithm.toLowerCase();
795
+ const match = lower.match(/^aes-(128|192|256)-(cbc|ctr|ecb|cfb|ofb|gcm)$/);
796
+ if (!match) {
797
+ throw new Error(`Unsupported cipher algorithm: ${algorithm}`);
798
+ }
799
+ const keyBits = parseInt(match[1]);
800
+ const mode = match[2];
801
+ return {
802
+ keySize: keyBits / 8,
803
+ ivSize: mode === "ecb" ? 0 : mode === "gcm" ? 12 : 16,
804
+ mode
805
+ };
767
806
  }
768
807
  function toBuffer(data, encoding) {
769
- if (typeof data === "string") {
770
- return Buffer.from(data, encoding || "utf8");
771
- }
772
- return Buffer.from(data);
808
+ if (typeof data === "string") {
809
+ return Buffer.from(data, encoding || "utf8");
810
+ }
811
+ return Buffer.from(data);
773
812
  }
774
813
  function encodeOutput(data, encoding) {
775
- if (!encoding) return Buffer.from(data);
776
- return Buffer.from(data).toString(encoding);
814
+ if (!encoding) return Buffer.from(data);
815
+ return Buffer.from(data).toString(encoding);
777
816
  }
817
+ /**
818
+ * Count how many trailing bytes at the end of a Uint8Array form an incomplete
819
+ * UTF-8 multibyte sequence. Returns 0 if the last character is complete.
820
+ */
778
821
  function incompleteUtf8Tail(buf) {
779
- if (buf.length === 0) return 0;
780
- const end = buf.length;
781
- for (let back = 1; back <= Math.min(4, end); back++) {
782
- const b = buf[end - back];
783
- if ((b & 128) === 0) {
784
- return 0;
785
- }
786
- if ((b & 192) === 128) {
787
- continue;
788
- }
789
- let expected;
790
- if ((b & 224) === 192) expected = 2;
791
- else if ((b & 240) === 224) expected = 3;
792
- else if ((b & 248) === 240) expected = 4;
793
- else return 0;
794
- return back < expected ? back : 0;
795
- }
796
- return 0;
822
+ if (buf.length === 0) return 0;
823
+ const end = buf.length;
824
+ for (let back = 1; back <= Math.min(4, end); back++) {
825
+ const b = buf[end - back];
826
+ if ((b & 128) === 0) {
827
+ return 0;
828
+ }
829
+ if ((b & 192) === 128) {
830
+ continue;
831
+ }
832
+ let expected;
833
+ if ((b & 224) === 192) expected = 2;
834
+ else if ((b & 240) === 224) expected = 3;
835
+ else if ((b & 248) === 240) expected = 4;
836
+ else return 0;
837
+ return back < expected ? back : 0;
838
+ }
839
+ return 0;
797
840
  }
798
841
  function pkcs7Pad(data) {
799
- const padLen = 16 - data.length % 16;
800
- const padded = new Uint8Array(data.length + padLen);
801
- padded.set(data);
802
- for (let i = data.length; i < padded.length; i++) padded[i] = padLen;
803
- return padded;
842
+ const padLen = 16 - data.length % 16;
843
+ const padded = new Uint8Array(data.length + padLen);
844
+ padded.set(data);
845
+ for (let i = data.length; i < padded.length; i++) padded[i] = padLen;
846
+ return padded;
804
847
  }
805
848
  function pkcs7Unpad(data) {
806
- if (data.length === 0 || data.length % 16 !== 0) {
807
- throw new Error("bad decrypt");
808
- }
809
- const padLen = data[data.length - 1];
810
- if (padLen === 0 || padLen > 16) {
811
- throw new Error("bad decrypt");
812
- }
813
- for (let i = data.length - padLen; i < data.length; i++) {
814
- if (data[i] !== padLen) throw new Error("bad decrypt");
815
- }
816
- return new Uint8Array(data.slice(0, data.length - padLen));
817
- }
818
- class CipherBase {
819
- _roundKeys;
820
- _iv;
821
- _mode;
822
- _buffer = new Uint8Array(0);
823
- _autoPadding = true;
824
- _finalized = false;
825
- constructor(algorithm, key, iv) {
826
- const info = parseAlgorithm(algorithm);
827
- if (key.length !== info.keySize) {
828
- throw new Error(`Invalid key length ${key.length}, expected ${info.keySize} for ${algorithm}`);
829
- }
830
- if (info.ivSize > 0 && (!iv || iv.length !== info.ivSize)) {
831
- throw new Error(`Invalid IV length ${iv?.length ?? 0}, expected ${info.ivSize} for ${algorithm}`);
832
- }
833
- this._roundKeys = keyExpansion(key);
834
- this._iv = iv ? new Uint8Array(iv) : new Uint8Array(16);
835
- this._mode = info.mode;
836
- }
837
- setAutoPadding(autoPadding) {
838
- this._autoPadding = autoPadding;
839
- return this;
840
- }
841
- }
842
- class Cipher extends CipherBase {
843
- _prevBlock;
844
- _counter;
845
- // GCM state
846
- _gcmH = null;
847
- // Hash subkey H = AES_K(0^128)
848
- _gcmJ0 = null;
849
- // Initial counter J0
850
- _gcmAAD = new Uint8Array(0);
851
- // Additional authenticated data
852
- _gcmCiphertext = [];
853
- // Accumulated ciphertext for GHASH
854
- _gcmCiphertextLen = 0;
855
- // Total ciphertext length
856
- _gcmAuthTag = null;
857
- // Computed authentication tag
858
- _gcmAADSet = false;
859
- // Whether setAAD was called
860
- constructor(algorithm, key, iv) {
861
- super(algorithm, key, iv);
862
- this._prevBlock = new Uint8Array(this._iv);
863
- if (this._mode === "gcm") {
864
- this._gcmH = aesEncryptBlock(new Uint8Array(16), this._roundKeys);
865
- this._gcmJ0 = new Uint8Array(16);
866
- this._gcmJ0.set(this._iv.subarray(0, 12));
867
- this._gcmJ0[15] = 1;
868
- this._counter = new Uint8Array(this._gcmJ0);
869
- gcmIncrementCounter(this._counter);
870
- } else {
871
- this._counter = new Uint8Array(this._iv);
872
- }
873
- }
874
- /**
875
- * Set Additional Authenticated Data for GCM mode.
876
- * Must be called before any update() calls.
877
- */
878
- setAAD(data) {
879
- if (this._mode !== "gcm") {
880
- throw new Error("setAAD is only supported in GCM mode");
881
- }
882
- if (this._gcmCiphertextLen > 0) {
883
- throw new Error("setAAD must be called before update()");
884
- }
885
- this._gcmAAD = new Uint8Array(data);
886
- this._gcmAADSet = true;
887
- return this;
888
- }
889
- /**
890
- * Get the authentication tag after final() has been called.
891
- * Only valid for GCM mode.
892
- */
893
- getAuthTag() {
894
- if (this._mode !== "gcm") {
895
- throw new Error("getAuthTag is only supported in GCM mode");
896
- }
897
- if (!this._gcmAuthTag) {
898
- throw new Error("getAuthTag must be called after final()");
899
- }
900
- return Buffer.from(this._gcmAuthTag);
901
- }
902
- update(data, inputEncoding, outputEncoding) {
903
- const input = toBuffer(data, inputEncoding);
904
- const combined = new Uint8Array(this._buffer.length + input.length);
905
- combined.set(this._buffer);
906
- combined.set(input, this._buffer.length);
907
- if (this._mode === "gcm") {
908
- const output2 = this._processGcmEncrypt(combined);
909
- this._buffer = new Uint8Array(0);
910
- return encodeOutput(output2, outputEncoding);
911
- }
912
- if (this._mode === "ctr" || this._mode === "cfb" || this._mode === "ofb") {
913
- const output2 = this._processStream(combined);
914
- this._buffer = new Uint8Array(0);
915
- return encodeOutput(output2, outputEncoding);
916
- }
917
- const fullBlocks = Math.floor(combined.length / 16);
918
- const processLen = fullBlocks * 16;
919
- const output = [];
920
- for (let i = 0; i < processLen; i += 16) {
921
- const block = combined.slice(i, i + 16);
922
- output.push(this._encryptBlock(block));
923
- }
924
- this._buffer = combined.slice(processLen);
925
- const result = new Uint8Array(output.length * 16);
926
- for (let i = 0; i < output.length; i++) result.set(output[i], i * 16);
927
- return encodeOutput(result, outputEncoding);
928
- }
929
- final(outputEncoding) {
930
- if (this._finalized) throw new Error("Cipher already finalized");
931
- this._finalized = true;
932
- if (this._mode === "gcm") {
933
- let finalOutput = new Uint8Array(0);
934
- if (this._buffer.length > 0) {
935
- finalOutput = this._processGcmEncrypt(this._buffer);
936
- this._buffer = new Uint8Array(0);
937
- }
938
- const allCiphertext = new Uint8Array(this._gcmCiphertextLen);
939
- let offset = 0;
940
- for (const chunk of this._gcmCiphertext) {
941
- allCiphertext.set(chunk, offset);
942
- offset += chunk.length;
943
- }
944
- const ghashResult = ghash(this._gcmH, this._gcmAAD, allCiphertext);
945
- const encJ0 = aesEncryptBlock(this._gcmJ0, this._roundKeys);
946
- const tag = new Uint8Array(16);
947
- for (let i = 0; i < 16; i++) tag[i] = ghashResult[i] ^ encJ0[i];
948
- this._gcmAuthTag = Buffer.from(tag);
949
- return encodeOutput(finalOutput, outputEncoding);
950
- }
951
- if (this._mode === "ctr" || this._mode === "cfb" || this._mode === "ofb") {
952
- if (this._buffer.length > 0) {
953
- const output2 = this._processStream(this._buffer);
954
- this._buffer = new Uint8Array(0);
955
- return encodeOutput(output2, outputEncoding);
956
- }
957
- return encodeOutput(new Uint8Array(0), outputEncoding);
958
- }
959
- let data = this._buffer;
960
- if (this._autoPadding) {
961
- data = pkcs7Pad(data);
962
- } else if (data.length % 16 !== 0) {
963
- throw new Error("data not multiple of block size");
964
- }
965
- const output = [];
966
- for (let i = 0; i < data.length; i += 16) {
967
- output.push(this._encryptBlock(data.slice(i, i + 16)));
968
- }
969
- this._buffer = new Uint8Array(0);
970
- if (output.length === 0) return encodeOutput(new Uint8Array(0), outputEncoding);
971
- const result = new Uint8Array(output.length * 16);
972
- for (let i = 0; i < output.length; i++) result.set(output[i], i * 16);
973
- return encodeOutput(result, outputEncoding);
974
- }
975
- _encryptBlock(block) {
976
- if (this._mode === "cbc") {
977
- const xored = new Uint8Array(16);
978
- for (let i = 0; i < 16; i++) xored[i] = block[i] ^ this._prevBlock[i];
979
- const encrypted = aesEncryptBlock(xored, this._roundKeys);
980
- this._prevBlock = encrypted;
981
- return encrypted;
982
- } else if (this._mode === "ecb") {
983
- return aesEncryptBlock(block, this._roundKeys);
984
- }
985
- throw new Error(`Block encryption not supported for mode: ${this._mode}`);
986
- }
987
- _processStream(data) {
988
- const output = new Uint8Array(data.length);
989
- for (let i = 0; i < data.length; i += 16) {
990
- const keystream = aesEncryptBlock(this._counter, this._roundKeys);
991
- const remaining = Math.min(16, data.length - i);
992
- for (let j = 0; j < remaining; j++) {
993
- output[i + j] = data[i + j] ^ keystream[j];
994
- }
995
- incrementCounter(this._counter);
996
- }
997
- return output;
998
- }
999
- /**
1000
- * GCM encryption: CTR mode encryption, also accumulates ciphertext for GHASH.
1001
- */
1002
- _processGcmEncrypt(data) {
1003
- const output = new Uint8Array(data.length);
1004
- for (let i = 0; i < data.length; i += 16) {
1005
- const keystream = aesEncryptBlock(this._counter, this._roundKeys);
1006
- const remaining = Math.min(16, data.length - i);
1007
- for (let j = 0; j < remaining; j++) {
1008
- output[i + j] = data[i + j] ^ keystream[j];
1009
- }
1010
- gcmIncrementCounter(this._counter);
1011
- }
1012
- this._gcmCiphertext.push(new Uint8Array(output));
1013
- this._gcmCiphertextLen += output.length;
1014
- return output;
1015
- }
1016
- }
1017
- class Decipher extends CipherBase {
1018
- _prevBlock;
1019
- _counter;
1020
- _pendingUtf8 = new Uint8Array(0);
1021
- // GCM state
1022
- _gcmH = null;
1023
- // Hash subkey H = AES_K(0^128)
1024
- _gcmJ0 = null;
1025
- // Initial counter J0
1026
- _gcmAAD = new Uint8Array(0);
1027
- // Additional authenticated data
1028
- _gcmCiphertext = [];
1029
- // Accumulated ciphertext for GHASH
1030
- _gcmCiphertextLen = 0;
1031
- // Total ciphertext length
1032
- _gcmExpectedTag = null;
1033
- // Expected authentication tag
1034
- _gcmAADSet = false;
1035
- // Whether setAAD was called
1036
- constructor(algorithm, key, iv) {
1037
- super(algorithm, key, iv);
1038
- this._prevBlock = new Uint8Array(this._iv);
1039
- if (this._mode === "gcm") {
1040
- this._gcmH = aesEncryptBlock(new Uint8Array(16), this._roundKeys);
1041
- this._gcmJ0 = new Uint8Array(16);
1042
- this._gcmJ0.set(this._iv.subarray(0, 12));
1043
- this._gcmJ0[15] = 1;
1044
- this._counter = new Uint8Array(this._gcmJ0);
1045
- gcmIncrementCounter(this._counter);
1046
- } else {
1047
- this._counter = new Uint8Array(this._iv);
1048
- }
1049
- }
1050
- /**
1051
- * Set Additional Authenticated Data for GCM mode.
1052
- * Must be called before any update() calls.
1053
- */
1054
- setAAD(data) {
1055
- if (this._mode !== "gcm") {
1056
- throw new Error("setAAD is only supported in GCM mode");
1057
- }
1058
- if (this._gcmCiphertextLen > 0) {
1059
- throw new Error("setAAD must be called before update()");
1060
- }
1061
- this._gcmAAD = new Uint8Array(data);
1062
- this._gcmAADSet = true;
1063
- return this;
1064
- }
1065
- /**
1066
- * Set the expected authentication tag for GCM decryption.
1067
- * Must be called before final().
1068
- */
1069
- setAuthTag(tag) {
1070
- if (this._mode !== "gcm") {
1071
- throw new Error("setAuthTag is only supported in GCM mode");
1072
- }
1073
- this._gcmExpectedTag = Buffer.from(tag);
1074
- return this;
1075
- }
1076
- _encodeWithUtf8Handling(bytes, encoding, isFinal) {
1077
- if (!encoding || encoding !== "utf8" && encoding !== "utf-8") {
1078
- return encodeOutput(bytes, encoding);
1079
- }
1080
- let data;
1081
- if (this._pendingUtf8.length > 0) {
1082
- data = new Uint8Array(this._pendingUtf8.length + bytes.length);
1083
- data.set(this._pendingUtf8);
1084
- data.set(bytes, this._pendingUtf8.length);
1085
- this._pendingUtf8 = new Uint8Array(0);
1086
- } else {
1087
- data = bytes;
1088
- }
1089
- if (!isFinal) {
1090
- const tail = incompleteUtf8Tail(data);
1091
- if (tail > 0) {
1092
- this._pendingUtf8 = new Uint8Array(data.slice(data.length - tail));
1093
- data = new Uint8Array(data.slice(0, data.length - tail));
1094
- }
1095
- }
1096
- return Buffer.from(data).toString("utf8");
1097
- }
1098
- update(data, inputEncoding, outputEncoding) {
1099
- const input = toBuffer(data, inputEncoding);
1100
- const combined = new Uint8Array(this._buffer.length + input.length);
1101
- combined.set(this._buffer);
1102
- combined.set(input, this._buffer.length);
1103
- if (this._mode === "gcm") {
1104
- this._gcmCiphertext.push(new Uint8Array(combined));
1105
- this._gcmCiphertextLen += combined.length;
1106
- const output2 = this._processGcmDecrypt(combined);
1107
- this._buffer = new Uint8Array(0);
1108
- return this._encodeWithUtf8Handling(output2, outputEncoding, false);
1109
- }
1110
- if (this._mode === "ctr" || this._mode === "cfb" || this._mode === "ofb") {
1111
- const output2 = this._processStream(combined);
1112
- this._buffer = new Uint8Array(0);
1113
- return this._encodeWithUtf8Handling(output2, outputEncoding, false);
1114
- }
1115
- const fullBlocks = Math.floor(combined.length / 16);
1116
- if (fullBlocks === 0) {
1117
- this._buffer = combined;
1118
- return this._encodeWithUtf8Handling(new Uint8Array(0), outputEncoding, false);
1119
- }
1120
- const processBlocks = this._autoPadding ? fullBlocks - 1 : fullBlocks;
1121
- const processLen = processBlocks * 16;
1122
- const output = [];
1123
- for (let i = 0; i < processLen; i += 16) {
1124
- const block = combined.slice(i, i + 16);
1125
- output.push(this._decryptBlock(block));
1126
- }
1127
- this._buffer = combined.slice(processLen);
1128
- const result = new Uint8Array(output.length * 16);
1129
- for (let i = 0; i < output.length; i++) result.set(output[i], i * 16);
1130
- return this._encodeWithUtf8Handling(result, outputEncoding, false);
1131
- }
1132
- final(outputEncoding) {
1133
- if (this._finalized) throw new Error("Decipher already finalized");
1134
- this._finalized = true;
1135
- if (this._mode === "gcm") {
1136
- let finalOutput = new Uint8Array(0);
1137
- if (this._buffer.length > 0) {
1138
- this._gcmCiphertext.push(new Uint8Array(this._buffer));
1139
- this._gcmCiphertextLen += this._buffer.length;
1140
- finalOutput = this._processGcmDecrypt(this._buffer);
1141
- this._buffer = new Uint8Array(0);
1142
- }
1143
- if (!this._gcmExpectedTag) {
1144
- throw new Error("Unsupported state or unable to authenticate data");
1145
- }
1146
- const allCiphertext = new Uint8Array(this._gcmCiphertextLen);
1147
- let offset = 0;
1148
- for (const chunk of this._gcmCiphertext) {
1149
- allCiphertext.set(chunk, offset);
1150
- offset += chunk.length;
1151
- }
1152
- const ghashResult = ghash(this._gcmH, this._gcmAAD, allCiphertext);
1153
- const encJ0 = aesEncryptBlock(this._gcmJ0, this._roundKeys);
1154
- const computedTag = new Uint8Array(16);
1155
- for (let i = 0; i < 16; i++) computedTag[i] = ghashResult[i] ^ encJ0[i];
1156
- const expectedTag = this._gcmExpectedTag;
1157
- const tagLen = Math.min(expectedTag.length, 16);
1158
- let diff = 0;
1159
- for (let i = 0; i < tagLen; i++) {
1160
- diff |= computedTag[i] ^ expectedTag[i];
1161
- }
1162
- if (diff !== 0) {
1163
- throw new Error("Unsupported state or unable to authenticate data");
1164
- }
1165
- return this._encodeWithUtf8Handling(finalOutput, outputEncoding, true);
1166
- }
1167
- if (this._mode === "ctr" || this._mode === "cfb" || this._mode === "ofb") {
1168
- if (this._buffer.length > 0) {
1169
- const output2 = this._processStream(this._buffer);
1170
- this._buffer = new Uint8Array(0);
1171
- return this._encodeWithUtf8Handling(output2, outputEncoding, true);
1172
- }
1173
- return this._encodeWithUtf8Handling(new Uint8Array(0), outputEncoding, true);
1174
- }
1175
- if (this._buffer.length === 0) {
1176
- return this._encodeWithUtf8Handling(new Uint8Array(0), outputEncoding, true);
1177
- }
1178
- if (this._buffer.length % 16 !== 0) {
1179
- throw new Error("bad decrypt");
1180
- }
1181
- const output = [];
1182
- for (let i = 0; i < this._buffer.length; i += 16) {
1183
- output.push(this._decryptBlock(this._buffer.slice(i, i + 16)));
1184
- }
1185
- const combined = new Uint8Array(output.length * 16);
1186
- for (let i = 0; i < output.length; i++) combined.set(output[i], i * 16);
1187
- const result = this._autoPadding ? pkcs7Unpad(combined) : combined;
1188
- this._buffer = new Uint8Array(0);
1189
- return this._encodeWithUtf8Handling(result, outputEncoding, true);
1190
- }
1191
- _decryptBlock(block) {
1192
- if (this._mode === "cbc") {
1193
- const decrypted = aesDecryptBlock(block, this._roundKeys);
1194
- const output = new Uint8Array(16);
1195
- for (let i = 0; i < 16; i++) output[i] = decrypted[i] ^ this._prevBlock[i];
1196
- this._prevBlock = new Uint8Array(block);
1197
- return output;
1198
- } else if (this._mode === "ecb") {
1199
- return aesDecryptBlock(block, this._roundKeys);
1200
- }
1201
- throw new Error(`Block decryption not supported for mode: ${this._mode}`);
1202
- }
1203
- _processStream(data) {
1204
- const output = new Uint8Array(data.length);
1205
- for (let i = 0; i < data.length; i += 16) {
1206
- const keystream = aesEncryptBlock(this._counter, this._roundKeys);
1207
- const remaining = Math.min(16, data.length - i);
1208
- for (let j = 0; j < remaining; j++) {
1209
- output[i + j] = data[i + j] ^ keystream[j];
1210
- }
1211
- incrementCounter(this._counter);
1212
- }
1213
- return output;
1214
- }
1215
- /**
1216
- * GCM decryption: CTR mode decryption (same as encryption, since CTR is symmetric).
1217
- */
1218
- _processGcmDecrypt(data) {
1219
- const output = new Uint8Array(data.length);
1220
- for (let i = 0; i < data.length; i += 16) {
1221
- const keystream = aesEncryptBlock(this._counter, this._roundKeys);
1222
- const remaining = Math.min(16, data.length - i);
1223
- for (let j = 0; j < remaining; j++) {
1224
- output[i + j] = data[i + j] ^ keystream[j];
1225
- }
1226
- gcmIncrementCounter(this._counter);
1227
- }
1228
- return output;
1229
- }
849
+ if (data.length === 0 || data.length % 16 !== 0) {
850
+ throw new Error("bad decrypt");
851
+ }
852
+ const padLen = data[data.length - 1];
853
+ if (padLen === 0 || padLen > 16) {
854
+ throw new Error("bad decrypt");
855
+ }
856
+ for (let i = data.length - padLen; i < data.length; i++) {
857
+ if (data[i] !== padLen) throw new Error("bad decrypt");
858
+ }
859
+ return new Uint8Array(data.slice(0, data.length - padLen));
1230
860
  }
861
+ var CipherBase = class {
862
+ _roundKeys;
863
+ _iv;
864
+ _mode;
865
+ _buffer = new Uint8Array(0);
866
+ _autoPadding = true;
867
+ _finalized = false;
868
+ constructor(algorithm, key, iv) {
869
+ const info = parseAlgorithm(algorithm);
870
+ if (key.length !== info.keySize) {
871
+ throw new Error(`Invalid key length ${key.length}, expected ${info.keySize} for ${algorithm}`);
872
+ }
873
+ if (info.ivSize > 0 && (!iv || iv.length !== info.ivSize)) {
874
+ throw new Error(`Invalid IV length ${iv?.length ?? 0}, expected ${info.ivSize} for ${algorithm}`);
875
+ }
876
+ this._roundKeys = keyExpansion(key);
877
+ this._iv = iv ? new Uint8Array(iv) : new Uint8Array(16);
878
+ this._mode = info.mode;
879
+ }
880
+ setAutoPadding(autoPadding) {
881
+ this._autoPadding = autoPadding;
882
+ return this;
883
+ }
884
+ };
885
+ var Cipher = class extends CipherBase {
886
+ _prevBlock;
887
+ _counter;
888
+ _gcmH = null;
889
+ _gcmJ0 = null;
890
+ _gcmAAD = new Uint8Array(0);
891
+ _gcmCiphertext = [];
892
+ _gcmCiphertextLen = 0;
893
+ _gcmAuthTag = null;
894
+ _gcmAADSet = false;
895
+ constructor(algorithm, key, iv) {
896
+ super(algorithm, key, iv);
897
+ this._prevBlock = new Uint8Array(this._iv);
898
+ if (this._mode === "gcm") {
899
+ this._gcmH = aesEncryptBlock(new Uint8Array(16), this._roundKeys);
900
+ this._gcmJ0 = new Uint8Array(16);
901
+ this._gcmJ0.set(this._iv.subarray(0, 12));
902
+ this._gcmJ0[15] = 1;
903
+ this._counter = new Uint8Array(this._gcmJ0);
904
+ gcmIncrementCounter(this._counter);
905
+ } else {
906
+ this._counter = new Uint8Array(this._iv);
907
+ }
908
+ }
909
+ /**
910
+ * Set Additional Authenticated Data for GCM mode.
911
+ * Must be called before any update() calls.
912
+ */
913
+ setAAD(data) {
914
+ if (this._mode !== "gcm") {
915
+ throw new Error("setAAD is only supported in GCM mode");
916
+ }
917
+ if (this._gcmCiphertextLen > 0) {
918
+ throw new Error("setAAD must be called before update()");
919
+ }
920
+ this._gcmAAD = new Uint8Array(data);
921
+ this._gcmAADSet = true;
922
+ return this;
923
+ }
924
+ /**
925
+ * Get the authentication tag after final() has been called.
926
+ * Only valid for GCM mode.
927
+ */
928
+ getAuthTag() {
929
+ if (this._mode !== "gcm") {
930
+ throw new Error("getAuthTag is only supported in GCM mode");
931
+ }
932
+ if (!this._gcmAuthTag) {
933
+ throw new Error("getAuthTag must be called after final()");
934
+ }
935
+ return Buffer.from(this._gcmAuthTag);
936
+ }
937
+ update(data, inputEncoding, outputEncoding) {
938
+ const input = toBuffer(data, inputEncoding);
939
+ const combined = new Uint8Array(this._buffer.length + input.length);
940
+ combined.set(this._buffer);
941
+ combined.set(input, this._buffer.length);
942
+ if (this._mode === "gcm") {
943
+ const output = this._processGcmEncrypt(combined);
944
+ this._buffer = new Uint8Array(0);
945
+ return encodeOutput(output, outputEncoding);
946
+ }
947
+ if (this._mode === "ctr" || this._mode === "cfb" || this._mode === "ofb") {
948
+ const output = this._processStream(combined);
949
+ this._buffer = new Uint8Array(0);
950
+ return encodeOutput(output, outputEncoding);
951
+ }
952
+ const fullBlocks = Math.floor(combined.length / 16);
953
+ const processLen = fullBlocks * 16;
954
+ const output = [];
955
+ for (let i = 0; i < processLen; i += 16) {
956
+ const block = combined.slice(i, i + 16);
957
+ output.push(this._encryptBlock(block));
958
+ }
959
+ this._buffer = combined.slice(processLen);
960
+ const result = new Uint8Array(output.length * 16);
961
+ for (let i = 0; i < output.length; i++) result.set(output[i], i * 16);
962
+ return encodeOutput(result, outputEncoding);
963
+ }
964
+ final(outputEncoding) {
965
+ if (this._finalized) throw new Error("Cipher already finalized");
966
+ this._finalized = true;
967
+ if (this._mode === "gcm") {
968
+ let finalOutput = new Uint8Array(0);
969
+ if (this._buffer.length > 0) {
970
+ finalOutput = this._processGcmEncrypt(this._buffer);
971
+ this._buffer = new Uint8Array(0);
972
+ }
973
+ const allCiphertext = new Uint8Array(this._gcmCiphertextLen);
974
+ let offset = 0;
975
+ for (const chunk of this._gcmCiphertext) {
976
+ allCiphertext.set(chunk, offset);
977
+ offset += chunk.length;
978
+ }
979
+ const ghashResult = ghash(this._gcmH, this._gcmAAD, allCiphertext);
980
+ const encJ0 = aesEncryptBlock(this._gcmJ0, this._roundKeys);
981
+ const tag = new Uint8Array(16);
982
+ for (let i = 0; i < 16; i++) tag[i] = ghashResult[i] ^ encJ0[i];
983
+ this._gcmAuthTag = Buffer.from(tag);
984
+ return encodeOutput(finalOutput, outputEncoding);
985
+ }
986
+ if (this._mode === "ctr" || this._mode === "cfb" || this._mode === "ofb") {
987
+ if (this._buffer.length > 0) {
988
+ const output = this._processStream(this._buffer);
989
+ this._buffer = new Uint8Array(0);
990
+ return encodeOutput(output, outputEncoding);
991
+ }
992
+ return encodeOutput(new Uint8Array(0), outputEncoding);
993
+ }
994
+ let data = this._buffer;
995
+ if (this._autoPadding) {
996
+ data = pkcs7Pad(data);
997
+ } else if (data.length % 16 !== 0) {
998
+ throw new Error("data not multiple of block size");
999
+ }
1000
+ const output = [];
1001
+ for (let i = 0; i < data.length; i += 16) {
1002
+ output.push(this._encryptBlock(data.slice(i, i + 16)));
1003
+ }
1004
+ this._buffer = new Uint8Array(0);
1005
+ if (output.length === 0) return encodeOutput(new Uint8Array(0), outputEncoding);
1006
+ const result = new Uint8Array(output.length * 16);
1007
+ for (let i = 0; i < output.length; i++) result.set(output[i], i * 16);
1008
+ return encodeOutput(result, outputEncoding);
1009
+ }
1010
+ _encryptBlock(block) {
1011
+ if (this._mode === "cbc") {
1012
+ const xored = new Uint8Array(16);
1013
+ for (let i = 0; i < 16; i++) xored[i] = block[i] ^ this._prevBlock[i];
1014
+ const encrypted = aesEncryptBlock(xored, this._roundKeys);
1015
+ this._prevBlock = encrypted;
1016
+ return encrypted;
1017
+ } else if (this._mode === "ecb") {
1018
+ return aesEncryptBlock(block, this._roundKeys);
1019
+ }
1020
+ throw new Error(`Block encryption not supported for mode: ${this._mode}`);
1021
+ }
1022
+ _processStream(data) {
1023
+ const output = new Uint8Array(data.length);
1024
+ for (let i = 0; i < data.length; i += 16) {
1025
+ const keystream = aesEncryptBlock(this._counter, this._roundKeys);
1026
+ const remaining = Math.min(16, data.length - i);
1027
+ for (let j = 0; j < remaining; j++) {
1028
+ output[i + j] = data[i + j] ^ keystream[j];
1029
+ }
1030
+ incrementCounter(this._counter);
1031
+ }
1032
+ return output;
1033
+ }
1034
+ /**
1035
+ * GCM encryption: CTR mode encryption, also accumulates ciphertext for GHASH.
1036
+ */
1037
+ _processGcmEncrypt(data) {
1038
+ const output = new Uint8Array(data.length);
1039
+ for (let i = 0; i < data.length; i += 16) {
1040
+ const keystream = aesEncryptBlock(this._counter, this._roundKeys);
1041
+ const remaining = Math.min(16, data.length - i);
1042
+ for (let j = 0; j < remaining; j++) {
1043
+ output[i + j] = data[i + j] ^ keystream[j];
1044
+ }
1045
+ gcmIncrementCounter(this._counter);
1046
+ }
1047
+ this._gcmCiphertext.push(new Uint8Array(output));
1048
+ this._gcmCiphertextLen += output.length;
1049
+ return output;
1050
+ }
1051
+ };
1052
+ var Decipher = class extends CipherBase {
1053
+ _prevBlock;
1054
+ _counter;
1055
+ _pendingUtf8 = new Uint8Array(0);
1056
+ _gcmH = null;
1057
+ _gcmJ0 = null;
1058
+ _gcmAAD = new Uint8Array(0);
1059
+ _gcmCiphertext = [];
1060
+ _gcmCiphertextLen = 0;
1061
+ _gcmExpectedTag = null;
1062
+ _gcmAADSet = false;
1063
+ constructor(algorithm, key, iv) {
1064
+ super(algorithm, key, iv);
1065
+ this._prevBlock = new Uint8Array(this._iv);
1066
+ if (this._mode === "gcm") {
1067
+ this._gcmH = aesEncryptBlock(new Uint8Array(16), this._roundKeys);
1068
+ this._gcmJ0 = new Uint8Array(16);
1069
+ this._gcmJ0.set(this._iv.subarray(0, 12));
1070
+ this._gcmJ0[15] = 1;
1071
+ this._counter = new Uint8Array(this._gcmJ0);
1072
+ gcmIncrementCounter(this._counter);
1073
+ } else {
1074
+ this._counter = new Uint8Array(this._iv);
1075
+ }
1076
+ }
1077
+ /**
1078
+ * Set Additional Authenticated Data for GCM mode.
1079
+ * Must be called before any update() calls.
1080
+ */
1081
+ setAAD(data) {
1082
+ if (this._mode !== "gcm") {
1083
+ throw new Error("setAAD is only supported in GCM mode");
1084
+ }
1085
+ if (this._gcmCiphertextLen > 0) {
1086
+ throw new Error("setAAD must be called before update()");
1087
+ }
1088
+ this._gcmAAD = new Uint8Array(data);
1089
+ this._gcmAADSet = true;
1090
+ return this;
1091
+ }
1092
+ /**
1093
+ * Set the expected authentication tag for GCM decryption.
1094
+ * Must be called before final().
1095
+ */
1096
+ setAuthTag(tag) {
1097
+ if (this._mode !== "gcm") {
1098
+ throw new Error("setAuthTag is only supported in GCM mode");
1099
+ }
1100
+ this._gcmExpectedTag = Buffer.from(tag);
1101
+ return this;
1102
+ }
1103
+ _encodeWithUtf8Handling(bytes, encoding, isFinal) {
1104
+ if (!encoding || encoding !== "utf8" && encoding !== "utf-8") {
1105
+ return encodeOutput(bytes, encoding);
1106
+ }
1107
+ let data;
1108
+ if (this._pendingUtf8.length > 0) {
1109
+ data = new Uint8Array(this._pendingUtf8.length + bytes.length);
1110
+ data.set(this._pendingUtf8);
1111
+ data.set(bytes, this._pendingUtf8.length);
1112
+ this._pendingUtf8 = new Uint8Array(0);
1113
+ } else {
1114
+ data = bytes;
1115
+ }
1116
+ if (!isFinal) {
1117
+ const tail = incompleteUtf8Tail(data);
1118
+ if (tail > 0) {
1119
+ this._pendingUtf8 = new Uint8Array(data.slice(data.length - tail));
1120
+ data = new Uint8Array(data.slice(0, data.length - tail));
1121
+ }
1122
+ }
1123
+ return Buffer.from(data).toString("utf8");
1124
+ }
1125
+ update(data, inputEncoding, outputEncoding) {
1126
+ const input = toBuffer(data, inputEncoding);
1127
+ const combined = new Uint8Array(this._buffer.length + input.length);
1128
+ combined.set(this._buffer);
1129
+ combined.set(input, this._buffer.length);
1130
+ if (this._mode === "gcm") {
1131
+ this._gcmCiphertext.push(new Uint8Array(combined));
1132
+ this._gcmCiphertextLen += combined.length;
1133
+ const output = this._processGcmDecrypt(combined);
1134
+ this._buffer = new Uint8Array(0);
1135
+ return this._encodeWithUtf8Handling(output, outputEncoding, false);
1136
+ }
1137
+ if (this._mode === "ctr" || this._mode === "cfb" || this._mode === "ofb") {
1138
+ const output = this._processStream(combined);
1139
+ this._buffer = new Uint8Array(0);
1140
+ return this._encodeWithUtf8Handling(output, outputEncoding, false);
1141
+ }
1142
+ const fullBlocks = Math.floor(combined.length / 16);
1143
+ if (fullBlocks === 0) {
1144
+ this._buffer = combined;
1145
+ return this._encodeWithUtf8Handling(new Uint8Array(0), outputEncoding, false);
1146
+ }
1147
+ const processBlocks = this._autoPadding ? fullBlocks - 1 : fullBlocks;
1148
+ const processLen = processBlocks * 16;
1149
+ const output = [];
1150
+ for (let i = 0; i < processLen; i += 16) {
1151
+ const block = combined.slice(i, i + 16);
1152
+ output.push(this._decryptBlock(block));
1153
+ }
1154
+ this._buffer = combined.slice(processLen);
1155
+ const result = new Uint8Array(output.length * 16);
1156
+ for (let i = 0; i < output.length; i++) result.set(output[i], i * 16);
1157
+ return this._encodeWithUtf8Handling(result, outputEncoding, false);
1158
+ }
1159
+ final(outputEncoding) {
1160
+ if (this._finalized) throw new Error("Decipher already finalized");
1161
+ this._finalized = true;
1162
+ if (this._mode === "gcm") {
1163
+ let finalOutput = new Uint8Array(0);
1164
+ if (this._buffer.length > 0) {
1165
+ this._gcmCiphertext.push(new Uint8Array(this._buffer));
1166
+ this._gcmCiphertextLen += this._buffer.length;
1167
+ finalOutput = this._processGcmDecrypt(this._buffer);
1168
+ this._buffer = new Uint8Array(0);
1169
+ }
1170
+ if (!this._gcmExpectedTag) {
1171
+ throw new Error("Unsupported state or unable to authenticate data");
1172
+ }
1173
+ const allCiphertext = new Uint8Array(this._gcmCiphertextLen);
1174
+ let offset = 0;
1175
+ for (const chunk of this._gcmCiphertext) {
1176
+ allCiphertext.set(chunk, offset);
1177
+ offset += chunk.length;
1178
+ }
1179
+ const ghashResult = ghash(this._gcmH, this._gcmAAD, allCiphertext);
1180
+ const encJ0 = aesEncryptBlock(this._gcmJ0, this._roundKeys);
1181
+ const computedTag = new Uint8Array(16);
1182
+ for (let i = 0; i < 16; i++) computedTag[i] = ghashResult[i] ^ encJ0[i];
1183
+ const expectedTag = this._gcmExpectedTag;
1184
+ const tagLen = Math.min(expectedTag.length, 16);
1185
+ let diff = 0;
1186
+ for (let i = 0; i < tagLen; i++) {
1187
+ diff |= computedTag[i] ^ expectedTag[i];
1188
+ }
1189
+ if (diff !== 0) {
1190
+ throw new Error("Unsupported state or unable to authenticate data");
1191
+ }
1192
+ return this._encodeWithUtf8Handling(finalOutput, outputEncoding, true);
1193
+ }
1194
+ if (this._mode === "ctr" || this._mode === "cfb" || this._mode === "ofb") {
1195
+ if (this._buffer.length > 0) {
1196
+ const output = this._processStream(this._buffer);
1197
+ this._buffer = new Uint8Array(0);
1198
+ return this._encodeWithUtf8Handling(output, outputEncoding, true);
1199
+ }
1200
+ return this._encodeWithUtf8Handling(new Uint8Array(0), outputEncoding, true);
1201
+ }
1202
+ if (this._buffer.length === 0) {
1203
+ return this._encodeWithUtf8Handling(new Uint8Array(0), outputEncoding, true);
1204
+ }
1205
+ if (this._buffer.length % 16 !== 0) {
1206
+ throw new Error("bad decrypt");
1207
+ }
1208
+ const output = [];
1209
+ for (let i = 0; i < this._buffer.length; i += 16) {
1210
+ output.push(this._decryptBlock(this._buffer.slice(i, i + 16)));
1211
+ }
1212
+ const combined = new Uint8Array(output.length * 16);
1213
+ for (let i = 0; i < output.length; i++) combined.set(output[i], i * 16);
1214
+ const result = this._autoPadding ? pkcs7Unpad(combined) : combined;
1215
+ this._buffer = new Uint8Array(0);
1216
+ return this._encodeWithUtf8Handling(result, outputEncoding, true);
1217
+ }
1218
+ _decryptBlock(block) {
1219
+ if (this._mode === "cbc") {
1220
+ const decrypted = aesDecryptBlock(block, this._roundKeys);
1221
+ const output = new Uint8Array(16);
1222
+ for (let i = 0; i < 16; i++) output[i] = decrypted[i] ^ this._prevBlock[i];
1223
+ this._prevBlock = new Uint8Array(block);
1224
+ return output;
1225
+ } else if (this._mode === "ecb") {
1226
+ return aesDecryptBlock(block, this._roundKeys);
1227
+ }
1228
+ throw new Error(`Block decryption not supported for mode: ${this._mode}`);
1229
+ }
1230
+ _processStream(data) {
1231
+ const output = new Uint8Array(data.length);
1232
+ for (let i = 0; i < data.length; i += 16) {
1233
+ const keystream = aesEncryptBlock(this._counter, this._roundKeys);
1234
+ const remaining = Math.min(16, data.length - i);
1235
+ for (let j = 0; j < remaining; j++) {
1236
+ output[i + j] = data[i + j] ^ keystream[j];
1237
+ }
1238
+ incrementCounter(this._counter);
1239
+ }
1240
+ return output;
1241
+ }
1242
+ /**
1243
+ * GCM decryption: CTR mode decryption (same as encryption, since CTR is symmetric).
1244
+ */
1245
+ _processGcmDecrypt(data) {
1246
+ const output = new Uint8Array(data.length);
1247
+ for (let i = 0; i < data.length; i += 16) {
1248
+ const keystream = aesEncryptBlock(this._counter, this._roundKeys);
1249
+ const remaining = Math.min(16, data.length - i);
1250
+ for (let j = 0; j < remaining; j++) {
1251
+ output[i + j] = data[i + j] ^ keystream[j];
1252
+ }
1253
+ gcmIncrementCounter(this._counter);
1254
+ }
1255
+ return output;
1256
+ }
1257
+ };
1231
1258
  function createCipher(_algorithm, _password) {
1232
- throw new Error("crypto.createCipher() is deprecated. Use createCipheriv() instead.");
1259
+ throw new Error("crypto.createCipher() is deprecated. Use createCipheriv() instead.");
1233
1260
  }
1234
1261
  function createCipheriv(algorithm, key, iv) {
1235
- const keyBuf = typeof key === "string" ? Buffer.from(key) : new Uint8Array(key);
1236
- const ivBuf = iv == null ? null : typeof iv === "string" ? Buffer.from(iv) : new Uint8Array(iv);
1237
- return new Cipher(algorithm, keyBuf, ivBuf);
1262
+ const keyBuf = typeof key === "string" ? Buffer.from(key) : new Uint8Array(key);
1263
+ const ivBuf = iv == null ? null : typeof iv === "string" ? Buffer.from(iv) : new Uint8Array(iv);
1264
+ return new Cipher(algorithm, keyBuf, ivBuf);
1238
1265
  }
1239
1266
  function createDecipher(_algorithm, _password) {
1240
- throw new Error("crypto.createDecipher() is deprecated. Use createDecipheriv() instead.");
1267
+ throw new Error("crypto.createDecipher() is deprecated. Use createDecipheriv() instead.");
1241
1268
  }
1242
1269
  function createDecipheriv(algorithm, key, iv) {
1243
- const keyBuf = typeof key === "string" ? Buffer.from(key) : new Uint8Array(key);
1244
- const ivBuf = iv == null ? null : typeof iv === "string" ? Buffer.from(iv) : new Uint8Array(iv);
1245
- return new Decipher(algorithm, keyBuf, ivBuf);
1270
+ const keyBuf = typeof key === "string" ? Buffer.from(key) : new Uint8Array(key);
1271
+ const ivBuf = iv == null ? null : typeof iv === "string" ? Buffer.from(iv) : new Uint8Array(iv);
1272
+ return new Decipher(algorithm, keyBuf, ivBuf);
1246
1273
  }
1247
1274
  function getCiphers() {
1248
- return [
1249
- "aes-128-cbc",
1250
- "aes-128-ecb",
1251
- "aes-192-cbc",
1252
- "aes-192-ecb",
1253
- "aes-256-cbc",
1254
- "aes-256-ecb",
1255
- "aes-128-ctr",
1256
- "aes-192-ctr",
1257
- "aes-256-ctr",
1258
- "aes-128-cfb",
1259
- "aes-192-cfb",
1260
- "aes-256-cfb",
1261
- "aes-128-gcm",
1262
- "aes-192-gcm",
1263
- "aes-256-gcm"
1264
- ];
1275
+ return [
1276
+ "aes-128-cbc",
1277
+ "aes-128-ecb",
1278
+ "aes-192-cbc",
1279
+ "aes-192-ecb",
1280
+ "aes-256-cbc",
1281
+ "aes-256-ecb",
1282
+ "aes-128-ctr",
1283
+ "aes-192-ctr",
1284
+ "aes-256-ctr",
1285
+ "aes-128-cfb",
1286
+ "aes-192-cfb",
1287
+ "aes-256-cfb",
1288
+ "aes-128-gcm",
1289
+ "aes-192-gcm",
1290
+ "aes-256-gcm"
1291
+ ];
1265
1292
  }
1266
- export {
1267
- createCipher,
1268
- createCipheriv,
1269
- createDecipher,
1270
- createDecipheriv,
1271
- getCiphers
1272
- };
1293
+
1294
+ //#endregion
1295
+ export { createCipher, createCipheriv, createDecipher, createDecipheriv, getCiphers };