aegis-aead 0.2.1 → 0.2.3

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.
Files changed (55) hide show
  1. package/README.md +29 -22
  2. package/dist/aegis128l.d.ts +33 -33
  3. package/dist/aegis128l.js +225 -235
  4. package/dist/aegis128x.d.ts +35 -35
  5. package/dist/aegis128x.js +348 -282
  6. package/dist/aegis256.d.ts +34 -51
  7. package/dist/aegis256.js +215 -206
  8. package/dist/aegis256x.d.ts +32 -33
  9. package/dist/aegis256x.js +333 -265
  10. package/dist/aes-bs.d.ts +46 -23
  11. package/dist/aes-bs.js +2273 -331
  12. package/dist/index.d.ts +4 -7
  13. package/dist/index.js +4 -7
  14. package/dist/random.d.ts +0 -1
  15. package/dist/random.js +0 -1
  16. package/dist/utils.d.ts +14 -0
  17. package/dist/utils.js +31 -0
  18. package/package.json +6 -6
  19. package/dist/aegis128l-bs.d.ts +0 -194
  20. package/dist/aegis128l-bs.d.ts.map +0 -1
  21. package/dist/aegis128l-bs.js +0 -549
  22. package/dist/aegis128l-bs.js.map +0 -1
  23. package/dist/aegis128l.d.ts.map +0 -1
  24. package/dist/aegis128l.js.map +0 -1
  25. package/dist/aegis128x.d.ts.map +0 -1
  26. package/dist/aegis128x.js.map +0 -1
  27. package/dist/aegis256-bs.d.ts +0 -183
  28. package/dist/aegis256-bs.d.ts.map +0 -1
  29. package/dist/aegis256-bs.js +0 -477
  30. package/dist/aegis256-bs.js.map +0 -1
  31. package/dist/aegis256.d.ts.map +0 -1
  32. package/dist/aegis256.js.map +0 -1
  33. package/dist/aegis256x.d.ts.map +0 -1
  34. package/dist/aegis256x.js.map +0 -1
  35. package/dist/aes-bs.d.ts.map +0 -1
  36. package/dist/aes-bs.js.map +0 -1
  37. package/dist/aes.d.ts +0 -81
  38. package/dist/aes.d.ts.map +0 -1
  39. package/dist/aes.js +0 -232
  40. package/dist/aes.js.map +0 -1
  41. package/dist/index.d.ts.map +0 -1
  42. package/dist/index.js.map +0 -1
  43. package/dist/random.d.ts.map +0 -1
  44. package/dist/random.js.map +0 -1
  45. package/src/aegis128l-bs.ts +0 -709
  46. package/src/aegis128l.ts +0 -653
  47. package/src/aegis128x.ts +0 -932
  48. package/src/aegis256-bs.ts +0 -625
  49. package/src/aegis256.ts +0 -597
  50. package/src/aegis256x.ts +0 -893
  51. package/src/aes-bs.ts +0 -459
  52. package/src/aes.ts +0 -271
  53. package/src/index.ts +0 -126
  54. package/src/random.ts +0 -41
  55. package/src/typed-array.d.ts +0 -18
package/src/aegis256.ts DELETED
@@ -1,597 +0,0 @@
1
- import {
2
- aesRoundTo,
3
- andBlocksTo,
4
- C0,
5
- C1,
6
- constantTimeEqual,
7
- le64To,
8
- xorBlocksTo,
9
- zeroPad,
10
- } from "./aes.js";
11
- import { randomBytes } from "./random.js";
12
-
13
- /**
14
- * AEGIS-256 cipher state.
15
- * Uses 6 AES blocks (96 bytes) of internal state and processes 16-byte blocks.
16
- */
17
- export class Aegis256State {
18
- private s0: Uint8Array;
19
- private s1: Uint8Array;
20
- private s2: Uint8Array;
21
- private s3: Uint8Array;
22
- private s4: Uint8Array;
23
- private s5: Uint8Array;
24
- private tmp: Uint8Array;
25
- private z: Uint8Array;
26
- private newS: Uint8Array[];
27
- private tBuf: Uint8Array;
28
-
29
- constructor() {
30
- this.s0 = new Uint8Array(16);
31
- this.s1 = new Uint8Array(16);
32
- this.s2 = new Uint8Array(16);
33
- this.s3 = new Uint8Array(16);
34
- this.s4 = new Uint8Array(16);
35
- this.s5 = new Uint8Array(16);
36
- this.tmp = new Uint8Array(16);
37
- this.z = new Uint8Array(16);
38
- this.newS = Array.from({ length: 6 }, () => new Uint8Array(16));
39
- this.tBuf = new Uint8Array(16);
40
- }
41
-
42
- get s(): Uint8Array[] {
43
- return [this.s0, this.s1, this.s2, this.s3, this.s4, this.s5];
44
- }
45
-
46
- set s(states: Uint8Array[]) {
47
- this.s0.set(states[0]!);
48
- this.s1.set(states[1]!);
49
- this.s2.set(states[2]!);
50
- this.s3.set(states[3]!);
51
- this.s4.set(states[4]!);
52
- this.s5.set(states[5]!);
53
- }
54
-
55
- /**
56
- * Initializes the state with a key and nonce.
57
- * @param key - 32-byte encryption key
58
- * @param nonce - 32-byte nonce (must be unique per message)
59
- */
60
- init(key: Uint8Array, nonce: Uint8Array): void {
61
- const k0 = key.subarray(0, 16);
62
- const k1 = key.subarray(16, 32);
63
- const n0 = nonce.subarray(0, 16);
64
- const n1 = nonce.subarray(16, 32);
65
-
66
- xorBlocksTo(k0, n0, this.s0);
67
- xorBlocksTo(k1, n1, this.s1);
68
- this.s2.set(C1);
69
- this.s3.set(C0);
70
- xorBlocksTo(k0, C0, this.s4);
71
- xorBlocksTo(k1, C1, this.s5);
72
-
73
- const k0Xorn0 = new Uint8Array(16);
74
- const k1Xorn1 = new Uint8Array(16);
75
- xorBlocksTo(k0, n0, k0Xorn0);
76
- xorBlocksTo(k1, n1, k1Xorn1);
77
-
78
- for (let i = 0; i < 4; i++) {
79
- this.update(k0);
80
- this.update(k1);
81
- this.update(k0Xorn0);
82
- this.update(k1Xorn1);
83
- }
84
- }
85
-
86
- /**
87
- * Updates the state with a 16-byte message block.
88
- * @param m - ArrayLike<number> - 16-byte message block
89
- */
90
- update(m: ArrayLike<number>): void {
91
- const newS = this.newS;
92
-
93
- xorBlocksTo(this.s0, m, this.tmp);
94
- aesRoundTo(this.s5, this.tmp, newS[0]!);
95
- aesRoundTo(this.s0, this.s1, newS[1]!);
96
- aesRoundTo(this.s1, this.s2, newS[2]!);
97
- aesRoundTo(this.s2, this.s3, newS[3]!);
98
- aesRoundTo(this.s3, this.s4, newS[4]!);
99
- aesRoundTo(this.s4, this.s5, newS[5]!);
100
-
101
- this.s0.set(newS[0]!);
102
- this.s1.set(newS[1]!);
103
- this.s2.set(newS[2]!);
104
- this.s3.set(newS[3]!);
105
- this.s4.set(newS[4]!);
106
- this.s5.set(newS[5]!);
107
- }
108
-
109
- /**
110
- * Absorbs a 16-byte associated data block into the state.
111
- * @param ai - 16-byte associated data block
112
- */
113
- absorb(ai: Uint8Array): void {
114
- this.update(ai);
115
- }
116
-
117
- /**
118
- * Encrypts a 16-byte plaintext block and writes to output.
119
- * @param xi - 16-byte plaintext block
120
- * @param out - 16-byte output buffer
121
- */
122
- encTo(xi: Uint8Array, out: Uint8Array): void {
123
- const z = this.z;
124
- const tmp = this.tmp;
125
-
126
- xorBlocksTo(this.s1, this.s4, z);
127
- for (let i = 0; i < 16; i++) z[i] ^= this.s5[i]!;
128
- andBlocksTo(this.s2, this.s3, tmp);
129
- for (let i = 0; i < 16; i++) z[i] ^= tmp[i]!;
130
-
131
- this.update(xi);
132
-
133
- for (let i = 0; i < 16; i++) out[i] = xi[i]! ^ z[i]!;
134
- }
135
-
136
- /**
137
- * Encrypts a 16-byte plaintext block.
138
- * @param xi - 16-byte plaintext block
139
- * @returns 16-byte ciphertext block
140
- */
141
- enc(xi: Uint8Array): Uint8Array {
142
- const out = new Uint8Array(16);
143
- this.encTo(xi, out);
144
- return out;
145
- }
146
-
147
- /**
148
- * Decrypts a 16-byte ciphertext block and writes to output.
149
- * @param ci - 16-byte ciphertext block
150
- * @param out - 16-byte output buffer
151
- */
152
- decTo(ci: Uint8Array, out: Uint8Array): void {
153
- const z = this.z;
154
- const tmp = this.tmp;
155
-
156
- xorBlocksTo(this.s1, this.s4, z);
157
- for (let i = 0; i < 16; i++) z[i] ^= this.s5[i]!;
158
- andBlocksTo(this.s2, this.s3, tmp);
159
- for (let i = 0; i < 16; i++) z[i] ^= tmp[i]!;
160
-
161
- for (let i = 0; i < 16; i++) out[i] = ci[i]! ^ z[i]!;
162
- this.update(out);
163
- }
164
-
165
- /**
166
- * Decrypts a 16-byte ciphertext block.
167
- * @param ci - 16-byte ciphertext block
168
- * @returns 16-byte plaintext block
169
- */
170
- dec(ci: Uint8Array): Uint8Array {
171
- const out = new Uint8Array(16);
172
- this.decTo(ci, out);
173
- return out;
174
- }
175
-
176
- /**
177
- * Encrypts a 16-byte plaintext block in-place.
178
- * @param block - 16-byte buffer (plaintext in, ciphertext out)
179
- */
180
- encInPlace(block: Uint8Array): void {
181
- this.encTo(block, block);
182
- }
183
-
184
- /**
185
- * Decrypts a 16-byte ciphertext block in-place.
186
- * @param block - 16-byte buffer (ciphertext in, plaintext out)
187
- */
188
- decInPlace(block: Uint8Array): void {
189
- this.decTo(block, block);
190
- }
191
-
192
- /**
193
- * Decrypts a partial (final) ciphertext block smaller than 16 bytes.
194
- * @param cn - Partial ciphertext block (1-15 bytes)
195
- * @returns Decrypted plaintext of the same length
196
- */
197
- decPartial(cn: Uint8Array): Uint8Array {
198
- const z = this.z;
199
- const tmp = this.tmp;
200
-
201
- xorBlocksTo(this.s1, this.s4, z);
202
- for (let i = 0; i < 16; i++) z[i] ^= this.s5[i]!;
203
- andBlocksTo(this.s2, this.s3, tmp);
204
- for (let i = 0; i < 16; i++) z[i] ^= tmp[i]!;
205
-
206
- const t = zeroPad(cn, 16);
207
- const out = new Uint8Array(16);
208
- for (let i = 0; i < 16; i++) out[i] = t[i]! ^ z[i]!;
209
- const xn = new Uint8Array(out.subarray(0, cn.length));
210
-
211
- const v = zeroPad(xn, 16);
212
- this.update(v);
213
-
214
- return xn;
215
- }
216
-
217
- /**
218
- * Finalizes encryption/decryption and produces an authentication tag.
219
- * @param adLenBits - Associated data length in bits
220
- * @param msgLenBits - Message length in bits
221
- * @param tagLen - Tag length (16 or 32 bytes)
222
- * @returns Authentication tag
223
- */
224
- finalize(
225
- adLenBits: bigint,
226
- msgLenBits: bigint,
227
- tagLen: 16 | 32 = 16,
228
- ): Uint8Array {
229
- const t = this.tBuf;
230
- le64To(adLenBits, t, 0);
231
- le64To(msgLenBits, t, 8);
232
- for (let i = 0; i < 16; i++) t[i] ^= this.s3[i]!;
233
-
234
- for (let i = 0; i < 7; i++) {
235
- this.update(t);
236
- }
237
-
238
- if (tagLen === 16) {
239
- const tag = new Uint8Array(16);
240
- for (let i = 0; i < 16; i++) {
241
- tag[i] =
242
- this.s0[i]! ^
243
- this.s1[i]! ^
244
- this.s2[i]! ^
245
- this.s3[i]! ^
246
- this.s4[i]! ^
247
- this.s5[i]!;
248
- }
249
- return tag;
250
- } else {
251
- const tag = new Uint8Array(32);
252
- for (let i = 0; i < 16; i++) {
253
- tag[i] = this.s0[i]! ^ this.s1[i]! ^ this.s2[i]!;
254
- }
255
- for (let i = 0; i < 16; i++) {
256
- tag[16 + i] = this.s3[i]! ^ this.s4[i]! ^ this.s5[i]!;
257
- }
258
- return tag;
259
- }
260
- }
261
- }
262
-
263
- /**
264
- * Encrypts a message using AEGIS-256 (detached mode).
265
- * @param msg - Plaintext message
266
- * @param ad - Associated data (authenticated but not encrypted)
267
- * @param key - 32-byte encryption key
268
- * @param nonce - 32-byte nonce (must be unique per message with the same key)
269
- * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
270
- * @returns Object containing ciphertext and authentication tag separately
271
- */
272
- export function aegis256EncryptDetached(
273
- msg: Uint8Array,
274
- ad: Uint8Array,
275
- key: Uint8Array,
276
- nonce: Uint8Array,
277
- tagLen: 16 | 32 = 16,
278
- ): { ciphertext: Uint8Array; tag: Uint8Array } {
279
- const state = new Aegis256State();
280
- state.init(key, nonce);
281
-
282
- const adPadded = zeroPad(ad, 16);
283
- for (let i = 0; i + 16 <= adPadded.length; i += 16) {
284
- state.absorb(adPadded.subarray(i, i + 16));
285
- }
286
-
287
- const msgPadded = zeroPad(msg, 16);
288
- const ct = new Uint8Array(msgPadded.length);
289
- for (let i = 0; i + 16 <= msgPadded.length; i += 16) {
290
- state.encTo(msgPadded.subarray(i, i + 16), ct.subarray(i, i + 16));
291
- }
292
-
293
- const tag = state.finalize(
294
- BigInt(ad.length * 8),
295
- BigInt(msg.length * 8),
296
- tagLen,
297
- );
298
- const ciphertext = new Uint8Array(ct.subarray(0, msg.length));
299
-
300
- return { ciphertext, tag };
301
- }
302
-
303
- /**
304
- * Decrypts a message using AEGIS-256 (detached mode).
305
- * @param ct - Ciphertext
306
- * @param tag - Authentication tag (16 or 32 bytes)
307
- * @param ad - Associated data (must match what was used during encryption)
308
- * @param key - 32-byte encryption key
309
- * @param nonce - 32-byte nonce (must match what was used during encryption)
310
- * @returns Decrypted plaintext, or null if authentication fails
311
- */
312
- export function aegis256DecryptDetached(
313
- ct: Uint8Array,
314
- tag: Uint8Array,
315
- ad: Uint8Array,
316
- key: Uint8Array,
317
- nonce: Uint8Array,
318
- ): Uint8Array | null {
319
- const tagLen = tag.length as 16 | 32;
320
- const state = new Aegis256State();
321
- state.init(key, nonce);
322
-
323
- const adPadded = zeroPad(ad, 16);
324
- for (let i = 0; i + 16 <= adPadded.length; i += 16) {
325
- state.absorb(adPadded.subarray(i, i + 16));
326
- }
327
-
328
- const fullBlocksLen = Math.floor(ct.length / 16) * 16;
329
- const cn = ct.subarray(fullBlocksLen);
330
-
331
- const msg = new Uint8Array(fullBlocksLen + (cn.length > 0 ? cn.length : 0));
332
- for (let i = 0; i + 16 <= ct.length; i += 16) {
333
- state.decTo(ct.subarray(i, i + 16), msg.subarray(i, i + 16));
334
- }
335
-
336
- if (cn.length > 0) {
337
- msg.set(state.decPartial(cn), fullBlocksLen);
338
- }
339
-
340
- const expectedTag = state.finalize(
341
- BigInt(ad.length * 8),
342
- BigInt(msg.length * 8),
343
- tagLen,
344
- );
345
-
346
- if (!constantTimeEqual(tag, expectedTag)) {
347
- msg.fill(0);
348
- return null;
349
- }
350
-
351
- return msg;
352
- }
353
-
354
- /**
355
- * Encrypts a message in-place using AEGIS-256 (detached mode).
356
- * The input buffer is modified to contain the ciphertext.
357
- * @param data - Buffer containing plaintext (will be overwritten with ciphertext)
358
- * @param ad - Associated data (authenticated but not encrypted)
359
- * @param key - 32-byte encryption key
360
- * @param nonce - 32-byte nonce (must be unique per message with the same key)
361
- * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
362
- * @returns Authentication tag
363
- */
364
- export function aegis256EncryptDetachedInPlace(
365
- data: Uint8Array,
366
- ad: Uint8Array,
367
- key: Uint8Array,
368
- nonce: Uint8Array,
369
- tagLen: 16 | 32 = 16,
370
- ): Uint8Array {
371
- const state = new Aegis256State();
372
- state.init(key, nonce);
373
-
374
- const adPadded = zeroPad(ad, 16);
375
- for (let i = 0; i + 16 <= adPadded.length; i += 16) {
376
- state.absorb(adPadded.subarray(i, i + 16));
377
- }
378
-
379
- const msgLen = data.length;
380
- const fullBlocksLen = Math.floor(msgLen / 16) * 16;
381
-
382
- for (let i = 0; i < fullBlocksLen; i += 16) {
383
- state.encInPlace(data.subarray(i, i + 16));
384
- }
385
-
386
- if (msgLen > fullBlocksLen) {
387
- const lastPartial = data.subarray(fullBlocksLen);
388
- const lastBlock = zeroPad(lastPartial, 16);
389
- const encBlock = state.enc(lastBlock);
390
- lastPartial.set(encBlock.subarray(0, lastPartial.length));
391
- }
392
-
393
- return state.finalize(BigInt(ad.length * 8), BigInt(msgLen * 8), tagLen);
394
- }
395
-
396
- /**
397
- * Decrypts a message in-place using AEGIS-256 (detached mode).
398
- * The input buffer is modified to contain the plaintext (or zeroed on failure).
399
- * @param data - Buffer containing ciphertext (will be overwritten with plaintext)
400
- * @param tag - Authentication tag (16 or 32 bytes)
401
- * @param ad - Associated data (must match what was used during encryption)
402
- * @param key - 32-byte encryption key
403
- * @param nonce - 32-byte nonce (must match what was used during encryption)
404
- * @returns True if authentication succeeds, false otherwise
405
- */
406
- export function aegis256DecryptDetachedInPlace(
407
- data: Uint8Array,
408
- tag: Uint8Array,
409
- ad: Uint8Array,
410
- key: Uint8Array,
411
- nonce: Uint8Array,
412
- ): boolean {
413
- const tagLen = tag.length as 16 | 32;
414
- const state = new Aegis256State();
415
- state.init(key, nonce);
416
-
417
- const adPadded = zeroPad(ad, 16);
418
- for (let i = 0; i + 16 <= adPadded.length; i += 16) {
419
- state.absorb(adPadded.subarray(i, i + 16));
420
- }
421
-
422
- const msgLen = data.length;
423
- const fullBlocksLen = Math.floor(msgLen / 16) * 16;
424
-
425
- for (let i = 0; i < fullBlocksLen; i += 16) {
426
- state.decInPlace(data.subarray(i, i + 16));
427
- }
428
-
429
- if (msgLen > fullBlocksLen) {
430
- const lastPartial = data.subarray(fullBlocksLen);
431
- const decrypted = state.decPartial(lastPartial);
432
- lastPartial.set(decrypted);
433
- }
434
-
435
- const expectedTag = state.finalize(
436
- BigInt(ad.length * 8),
437
- BigInt(msgLen * 8),
438
- tagLen,
439
- );
440
-
441
- if (!constantTimeEqual(tag, expectedTag)) {
442
- data.fill(0);
443
- return false;
444
- }
445
-
446
- return true;
447
- }
448
-
449
- /** Nonce size for AEGIS-256 in bytes. */
450
- export const AEGIS_256_NONCE_SIZE = 32;
451
-
452
- /** Key size for AEGIS-256 in bytes. */
453
- export const AEGIS_256_KEY_SIZE = 32;
454
-
455
- /**
456
- * Encrypts a message using AEGIS-256.
457
- * Returns a single buffer containing nonce || ciphertext || tag.
458
- * @param msg - Plaintext message
459
- * @param ad - Associated data (authenticated but not encrypted)
460
- * @param key - 32-byte encryption key
461
- * @param nonce - 32-byte nonce (optional, generates random nonce if not provided)
462
- * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
463
- * @returns Concatenated nonce || ciphertext || tag
464
- */
465
- export function aegis256Encrypt(
466
- msg: Uint8Array,
467
- ad: Uint8Array,
468
- key: Uint8Array,
469
- nonce: Uint8Array | null = null,
470
- tagLen: 16 | 32 = 16,
471
- ): Uint8Array {
472
- const actualNonce = nonce ?? randomBytes(AEGIS_256_NONCE_SIZE);
473
- const state = new Aegis256State();
474
- state.init(key, actualNonce);
475
-
476
- const adPadded = zeroPad(ad, 16);
477
- for (let i = 0; i + 16 <= adPadded.length; i += 16) {
478
- state.absorb(adPadded.subarray(i, i + 16));
479
- }
480
-
481
- const nonceSize = AEGIS_256_NONCE_SIZE;
482
- const result = new Uint8Array(nonceSize + msg.length + tagLen);
483
- result.set(actualNonce, 0);
484
-
485
- const fullBlocks = Math.floor(msg.length / 16) * 16;
486
- for (let i = 0; i < fullBlocks; i += 16) {
487
- state.encTo(
488
- msg.subarray(i, i + 16),
489
- result.subarray(nonceSize + i, nonceSize + i + 16),
490
- );
491
- }
492
-
493
- if (msg.length > fullBlocks) {
494
- const lastBlock = zeroPad(msg.subarray(fullBlocks), 16);
495
- const encBlock = state.enc(lastBlock);
496
- result.set(
497
- encBlock.subarray(0, msg.length - fullBlocks),
498
- nonceSize + fullBlocks,
499
- );
500
- }
501
-
502
- const tag = state.finalize(
503
- BigInt(ad.length * 8),
504
- BigInt(msg.length * 8),
505
- tagLen,
506
- );
507
- result.set(tag, nonceSize + msg.length);
508
-
509
- return result;
510
- }
511
-
512
- /**
513
- * Decrypts a message using AEGIS-256.
514
- * Expects input as nonce || ciphertext || tag.
515
- * @param sealed - Concatenated nonce || ciphertext || tag
516
- * @param ad - Associated data (must match what was used during encryption)
517
- * @param key - 32-byte encryption key
518
- * @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
519
- * @returns Decrypted plaintext, or null if authentication fails
520
- */
521
- export function aegis256Decrypt(
522
- sealed: Uint8Array,
523
- ad: Uint8Array,
524
- key: Uint8Array,
525
- tagLen: 16 | 32 = 16,
526
- ): Uint8Array | null {
527
- const nonceSize = AEGIS_256_NONCE_SIZE;
528
- if (sealed.length < nonceSize + tagLen) {
529
- return null;
530
- }
531
- const nonce = sealed.subarray(0, nonceSize);
532
- const ct = sealed.subarray(nonceSize, sealed.length - tagLen);
533
- const tag = sealed.subarray(sealed.length - tagLen);
534
- return aegis256DecryptDetached(ct, tag, ad, key, nonce);
535
- }
536
-
537
- /**
538
- * Computes a MAC (Message Authentication Code) using AEGIS-256.
539
- * @param data - Data to authenticate
540
- * @param key - 32-byte key
541
- * @param nonce - 32-byte nonce (optional, uses zero nonce if null)
542
- * @param tagLen - Tag length: 16 or 32 bytes (default: 16)
543
- * @returns Authentication tag
544
- */
545
- export function aegis256Mac(
546
- data: Uint8Array,
547
- key: Uint8Array,
548
- nonce: Uint8Array | null = null,
549
- tagLen: 16 | 32 = 16,
550
- ): Uint8Array {
551
- const state = new Aegis256State();
552
- state.init(key, nonce ?? new Uint8Array(32));
553
-
554
- const dataPadded = zeroPad(data, 16);
555
- for (let i = 0; i + 16 <= dataPadded.length; i += 16) {
556
- state.absorb(dataPadded.subarray(i, i + 16));
557
- }
558
-
559
- return state.finalize(BigInt(data.length * 8), BigInt(tagLen * 8), tagLen);
560
- }
561
-
562
- /**
563
- * Verifies a MAC computed using AEGIS-256.
564
- * @param data - Data to verify
565
- * @param tag - Expected authentication tag (16 or 32 bytes)
566
- * @param key - 32-byte key
567
- * @param nonce - 32-byte nonce (optional, uses zero nonce if null)
568
- * @returns True if the tag is valid, false otherwise
569
- */
570
- export function aegis256MacVerify(
571
- data: Uint8Array,
572
- tag: Uint8Array,
573
- key: Uint8Array,
574
- nonce: Uint8Array | null = null,
575
- ): boolean {
576
- const tagLen = tag.length as 16 | 32;
577
- const expectedTag = aegis256Mac(data, key, nonce, tagLen);
578
- return constantTimeEqual(tag, expectedTag);
579
- }
580
-
581
- /**
582
- * Generates a random 32-byte key for AEGIS-256.
583
- * @returns 32-byte encryption key
584
- * @throws Error if no cryptographic random source is available
585
- */
586
- export function aegis256CreateKey(): Uint8Array {
587
- return randomBytes(AEGIS_256_KEY_SIZE);
588
- }
589
-
590
- /**
591
- * Generates a random 32-byte nonce for AEGIS-256.
592
- * @returns 32-byte nonce
593
- * @throws Error if no cryptographic random source is available
594
- */
595
- export function aegis256CreateNonce(): Uint8Array {
596
- return randomBytes(AEGIS_256_NONCE_SIZE);
597
- }