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/dist/aegis128l.js CHANGED
@@ -1,47 +1,61 @@
1
- import { aesRoundTo, andBlocksTo, C0, C1, constantTimeEqual, le64To, xorBlocksTo, zeroPad, } from "./aes.js";
1
+ /**
2
+ * AEGIS-128L implementation.
3
+ * Built on the constant-time bitsliced AES core, which processes all 8 state
4
+ * blocks simultaneously without lookup tables.
5
+ */
6
+ import { aegisRound128, blockFromBytes, blocksPut, blockToBytes, blockXor, createAesBlock, createAesBlocks, keystream128, pack, packConstantInput128, unpack, wordIdx, } from "./aes-bs.js";
2
7
  import { randomBytes } from "./random.js";
8
+ import { constantTimeEqual, zeroPad } from "./utils.js";
9
+ const RATE = 32;
10
+ const C0 = new Uint32Array([
11
+ 0x02010100, 0x0d080503, 0x59372215, 0x6279e990,
12
+ ]);
13
+ const C1 = new Uint32Array([
14
+ 0x55183ddb, 0xf12fc26d, 0x42311120, 0xdd28b573,
15
+ ]);
3
16
  /**
4
17
  * AEGIS-128L cipher state.
5
- * Uses 8 AES blocks (128 bytes) of internal state and processes 32-byte blocks.
18
+ * The state is kept in packed bitsliced form between operations so that
19
+ * pack/unpack does not need to be applied at every round.
6
20
  */
7
21
  export class Aegis128LState {
8
22
  constructor() {
9
- this.s0 = new Uint8Array(16);
10
- this.s1 = new Uint8Array(16);
11
- this.s2 = new Uint8Array(16);
12
- this.s3 = new Uint8Array(16);
13
- this.s4 = new Uint8Array(16);
14
- this.s5 = new Uint8Array(16);
15
- this.s6 = new Uint8Array(16);
16
- this.s7 = new Uint8Array(16);
17
- this.tmp0 = new Uint8Array(16);
18
- this.tmp1 = new Uint8Array(16);
19
- this.z0 = new Uint8Array(16);
20
- this.z1 = new Uint8Array(16);
21
- this.newS = Array.from({ length: 8 }, () => new Uint8Array(16));
22
- this.tBuf = new Uint8Array(16);
23
+ this.st = createAesBlocks();
24
+ this.constantInput = createAesBlocks();
25
+ this.tmp0 = createAesBlock();
26
+ this.tmp1 = createAesBlock();
27
+ this.z0 = createAesBlock();
28
+ this.z1 = createAesBlock();
23
29
  }
30
+ /**
31
+ * Returns the 8 state blocks as byte arrays (for testing).
32
+ */
24
33
  get s() {
25
- return [
26
- this.s0,
27
- this.s1,
28
- this.s2,
29
- this.s3,
30
- this.s4,
31
- this.s5,
32
- this.s6,
33
- this.s7,
34
- ];
34
+ const unpacked = createAesBlocks();
35
+ unpacked.set(this.st);
36
+ unpack(unpacked);
37
+ const blocks = [];
38
+ const w = createAesBlock();
39
+ for (let i = 0; i < 8; i++) {
40
+ for (let j = 0; j < 4; j++)
41
+ w[j] = unpacked[wordIdx(i, j)];
42
+ const bytes = new Uint8Array(16);
43
+ blockToBytes(bytes, w);
44
+ blocks.push(bytes);
45
+ }
46
+ return blocks;
35
47
  }
36
- set s(states) {
37
- this.s0.set(states[0]);
38
- this.s1.set(states[1]);
39
- this.s2.set(states[2]);
40
- this.s3.set(states[3]);
41
- this.s4.set(states[4]);
42
- this.s5.set(states[5]);
43
- this.s6.set(states[6]);
44
- this.s7.set(states[7]);
48
+ /**
49
+ * Sets the 8 state blocks from byte arrays (for testing).
50
+ */
51
+ set s(blocks) {
52
+ this.st.fill(0);
53
+ const w = createAesBlock();
54
+ for (let i = 0; i < 8; i++) {
55
+ blockFromBytes(w, blocks[i]);
56
+ blocksPut(this.st, w, i);
57
+ }
58
+ pack(this.st);
45
59
  }
46
60
  /**
47
61
  * Initializes the state with a key and nonce.
@@ -49,16 +63,28 @@ export class Aegis128LState {
49
63
  * @param nonce - 16-byte nonce (must be unique per message)
50
64
  */
51
65
  init(key, nonce) {
52
- xorBlocksTo(key, nonce, this.s0);
53
- this.s1.set(C1);
54
- this.s2.set(C0);
55
- this.s3.set(C1);
56
- xorBlocksTo(key, nonce, this.s4);
57
- xorBlocksTo(key, C0, this.s5);
58
- xorBlocksTo(key, C1, this.s6);
59
- xorBlocksTo(key, C0, this.s7);
66
+ const k = createAesBlock();
67
+ const n = createAesBlock();
68
+ const kn = createAesBlock();
69
+ const kc0 = createAesBlock();
70
+ const kc1 = createAesBlock();
71
+ blockFromBytes(k, key);
72
+ blockFromBytes(n, nonce);
73
+ blockXor(kn, k, n);
74
+ blockXor(kc0, k, C0);
75
+ blockXor(kc1, k, C1);
76
+ blocksPut(this.st, kn, 0);
77
+ blocksPut(this.st, C1, 1);
78
+ blocksPut(this.st, C0, 2);
79
+ blocksPut(this.st, C1, 3);
80
+ blocksPut(this.st, kn, 4);
81
+ blocksPut(this.st, kc0, 5);
82
+ blocksPut(this.st, kc1, 6);
83
+ blocksPut(this.st, kc0, 7);
84
+ packConstantInput128(this.constantInput, n, k);
85
+ pack(this.st);
60
86
  for (let i = 0; i < 10; i++) {
61
- this.update(nonce, key);
87
+ aegisRound128(this.st, this.constantInput);
62
88
  }
63
89
  }
64
90
  /**
@@ -67,57 +93,43 @@ export class Aegis128LState {
67
93
  * @param m1 - Second 16-byte message block
68
94
  */
69
95
  update(m0, m1) {
70
- const newS = this.newS;
71
- xorBlocksTo(this.s0, m0, this.tmp0);
72
- aesRoundTo(this.s7, this.tmp0, newS[0]);
73
- aesRoundTo(this.s0, this.s1, newS[1]);
74
- aesRoundTo(this.s1, this.s2, newS[2]);
75
- aesRoundTo(this.s2, this.s3, newS[3]);
76
- xorBlocksTo(this.s4, m1, this.tmp1);
77
- aesRoundTo(this.s3, this.tmp1, newS[4]);
78
- aesRoundTo(this.s4, this.s5, newS[5]);
79
- aesRoundTo(this.s5, this.s6, newS[6]);
80
- aesRoundTo(this.s6, this.s7, newS[7]);
81
- this.s0.set(newS[0]);
82
- this.s1.set(newS[1]);
83
- this.s2.set(newS[2]);
84
- this.s3.set(newS[3]);
85
- this.s4.set(newS[4]);
86
- this.s5.set(newS[5]);
87
- this.s6.set(newS[6]);
88
- this.s7.set(newS[7]);
96
+ blockFromBytes(this.tmp0, m0);
97
+ blockFromBytes(this.tmp1, m1);
98
+ packConstantInput128(this.constantInput, this.tmp0, this.tmp1);
99
+ aegisRound128(this.st, this.constantInput);
89
100
  }
90
101
  /**
91
102
  * Absorbs a 32-byte associated data block into the state.
92
- * @param ai - 32-byte associated data block
103
+ * @param ai - Buffer holding the 32-byte associated data block
104
+ * @param off - Offset of the block within the buffer
93
105
  */
94
- absorb(ai) {
95
- this.update(ai.subarray(0, 16), ai.subarray(16, 32));
106
+ absorb(ai, off = 0) {
107
+ const msg0 = this.tmp0;
108
+ const msg1 = this.tmp1;
109
+ blockFromBytes(msg0, ai, off);
110
+ blockFromBytes(msg1, ai, off + 16);
111
+ packConstantInput128(this.constantInput, msg0, msg1);
112
+ aegisRound128(this.st, this.constantInput);
96
113
  }
97
114
  /**
98
115
  * Encrypts a 32-byte plaintext block and writes to output buffer.
99
- * @param xi - 32-byte plaintext block
100
- * @param out - 32-byte output buffer
116
+ * @param xi - Buffer holding the 32-byte plaintext block
117
+ * @param out - Output buffer receiving the 32-byte ciphertext block
118
+ * @param inOff - Offset of the plaintext block within xi
119
+ * @param outOff - Offset of the ciphertext block within out
101
120
  */
102
- encTo(xi, out) {
103
- const z0 = this.z0;
104
- const z1 = this.z1;
105
- const tmp = this.tmp0;
106
- xorBlocksTo(this.s1, this.s6, z0);
107
- andBlocksTo(this.s2, this.s3, tmp);
108
- for (let i = 0; i < 16; i++)
109
- z0[i] ^= tmp[i];
110
- xorBlocksTo(this.s2, this.s5, z1);
111
- andBlocksTo(this.s6, this.s7, tmp);
112
- for (let i = 0; i < 16; i++)
113
- z1[i] ^= tmp[i];
114
- const t0 = xi.subarray(0, 16);
115
- const t1 = xi.subarray(16, 32);
116
- for (let i = 0; i < 16; i++)
117
- out[i] = t0[i] ^ z0[i];
118
- for (let i = 0; i < 16; i++)
119
- out[16 + i] = t1[i] ^ z1[i];
120
- this.update(t0, t1);
121
+ encTo(xi, out, inOff = 0, outOff = 0) {
122
+ const t0 = this.tmp0;
123
+ const t1 = this.tmp1;
124
+ keystream128(this.st, this.z0, this.z1);
125
+ blockFromBytes(t0, xi, inOff);
126
+ blockFromBytes(t1, xi, inOff + 16);
127
+ packConstantInput128(this.constantInput, t0, t1);
128
+ aegisRound128(this.st, this.constantInput);
129
+ blockXor(t0, t0, this.z0);
130
+ blockXor(t1, t1, this.z1);
131
+ blockToBytes(out, t0, outOff);
132
+ blockToBytes(out, t1, outOff + 16);
121
133
  }
122
134
  /**
123
135
  * Encrypts a 32-byte plaintext block.
@@ -131,28 +143,23 @@ export class Aegis128LState {
131
143
  }
132
144
  /**
133
145
  * Decrypts a 32-byte ciphertext block and writes to output buffer.
134
- * @param ci - 32-byte ciphertext block
135
- * @param out - 32-byte output buffer
146
+ * @param ci - Buffer holding the 32-byte ciphertext block
147
+ * @param out - Output buffer receiving the 32-byte plaintext block
148
+ * @param inOff - Offset of the ciphertext block within ci
149
+ * @param outOff - Offset of the plaintext block within out
136
150
  */
137
- decTo(ci, out) {
138
- const z0 = this.z0;
139
- const z1 = this.z1;
140
- const tmp = this.tmp0;
141
- xorBlocksTo(this.s1, this.s6, z0);
142
- andBlocksTo(this.s2, this.s3, tmp);
143
- for (let i = 0; i < 16; i++)
144
- z0[i] ^= tmp[i];
145
- xorBlocksTo(this.s2, this.s5, z1);
146
- andBlocksTo(this.s6, this.s7, tmp);
147
- for (let i = 0; i < 16; i++)
148
- z1[i] ^= tmp[i];
149
- const t0 = ci.subarray(0, 16);
150
- const t1 = ci.subarray(16, 32);
151
- for (let i = 0; i < 16; i++)
152
- out[i] = t0[i] ^ z0[i];
153
- for (let i = 0; i < 16; i++)
154
- out[16 + i] = t1[i] ^ z1[i];
155
- this.update(out.subarray(0, 16), out.subarray(16, 32));
151
+ decTo(ci, out, inOff = 0, outOff = 0) {
152
+ const msg0 = this.tmp0;
153
+ const msg1 = this.tmp1;
154
+ blockFromBytes(msg0, ci, inOff);
155
+ blockFromBytes(msg1, ci, inOff + 16);
156
+ keystream128(this.st, this.z0, this.z1);
157
+ blockXor(msg0, msg0, this.z0);
158
+ blockXor(msg1, msg1, this.z1);
159
+ packConstantInput128(this.constantInput, msg0, msg1);
160
+ aegisRound128(this.st, this.constantInput);
161
+ blockToBytes(out, msg0, outOff);
162
+ blockToBytes(out, msg1, outOff + 16);
156
163
  }
157
164
  /**
158
165
  * Decrypts a 32-byte ciphertext block.
@@ -164,32 +171,9 @@ export class Aegis128LState {
164
171
  this.decTo(ci, out);
165
172
  return out;
166
173
  }
167
- /**
168
- * Encrypts a 32-byte plaintext block in-place.
169
- * @param block - 32-byte buffer (plaintext in, ciphertext out)
170
- */
171
174
  encInPlace(block) {
172
- const z0 = this.z0;
173
- const z1 = this.z1;
174
- const tmp = this.tmp0;
175
- xorBlocksTo(this.s1, this.s6, z0);
176
- andBlocksTo(this.s2, this.s3, tmp);
177
- for (let i = 0; i < 16; i++)
178
- z0[i] ^= tmp[i];
179
- xorBlocksTo(this.s2, this.s5, z1);
180
- andBlocksTo(this.s6, this.s7, tmp);
181
- for (let i = 0; i < 16; i++)
182
- z1[i] ^= tmp[i];
183
- this.update(block.subarray(0, 16), block.subarray(16, 32));
184
- for (let i = 0; i < 16; i++)
185
- block[i] ^= z0[i];
186
- for (let i = 0; i < 16; i++)
187
- block[16 + i] ^= z1[i];
175
+ this.encTo(block, block);
188
176
  }
189
- /**
190
- * Decrypts a 32-byte ciphertext block in-place.
191
- * @param block - 32-byte buffer (ciphertext in, plaintext out)
192
- */
193
177
  decInPlace(block) {
194
178
  this.decTo(block, block);
195
179
  }
@@ -199,68 +183,87 @@ export class Aegis128LState {
199
183
  * @returns Decrypted plaintext of the same length
200
184
  */
201
185
  decPartial(cn) {
202
- const z0 = this.z0;
203
- const z1 = this.z1;
204
- const tmp = this.tmp0;
205
- xorBlocksTo(this.s1, this.s6, z0);
206
- andBlocksTo(this.s2, this.s3, tmp);
207
- for (let i = 0; i < 16; i++)
208
- z0[i] ^= tmp[i];
209
- xorBlocksTo(this.s2, this.s5, z1);
210
- andBlocksTo(this.s6, this.s7, tmp);
211
- for (let i = 0; i < 16; i++)
212
- z1[i] ^= tmp[i];
213
- const padded = zeroPad(cn, 32);
214
- const t0 = padded.subarray(0, 16);
215
- const t1 = padded.subarray(16, 32);
216
- const out = new Uint8Array(32);
217
- for (let i = 0; i < 16; i++)
218
- out[i] = t0[i] ^ z0[i];
219
- for (let i = 0; i < 16; i++)
220
- out[16 + i] = t1[i] ^ z1[i];
221
- const xn = new Uint8Array(out.subarray(0, cn.length));
222
- const v = zeroPad(xn, 32);
223
- this.update(v.subarray(0, 16), v.subarray(16, 32));
186
+ const msg0 = this.tmp0;
187
+ const msg1 = this.tmp1;
188
+ const padded = zeroPad(cn, RATE);
189
+ blockFromBytes(msg0, padded);
190
+ blockFromBytes(msg1, padded, 16);
191
+ keystream128(this.st, this.z0, this.z1);
192
+ blockXor(msg0, msg0, this.z0);
193
+ blockXor(msg1, msg1, this.z1);
194
+ const pad = new Uint8Array(RATE);
195
+ blockToBytes(pad, msg0);
196
+ blockToBytes(pad, msg1, 16);
197
+ const xn = new Uint8Array(pad.subarray(0, cn.length));
198
+ pad.fill(0, cn.length);
199
+ blockFromBytes(msg0, pad);
200
+ blockFromBytes(msg1, pad, 16);
201
+ packConstantInput128(this.constantInput, msg0, msg1);
202
+ aegisRound128(this.st, this.constantInput);
224
203
  return xn;
225
204
  }
226
205
  /**
227
206
  * Finalizes encryption/decryption and produces an authentication tag.
228
- * @param adLenBits - Associated data length in bits
229
- * @param msgLenBits - Message length in bits
207
+ * @param adLen - Associated data length in bytes
208
+ * @param msgLen - Message length in bytes
230
209
  * @param tagLen - Tag length (16 or 32 bytes)
231
210
  * @returns Authentication tag
232
211
  */
233
- finalize(adLenBits, msgLenBits, tagLen = 16) {
234
- const t = this.tBuf;
235
- le64To(adLenBits, t, 0);
236
- le64To(msgLenBits, t, 8);
237
- for (let i = 0; i < 16; i++)
238
- t[i] ^= this.s2[i];
212
+ finalize(adLen, msgLen, tagLen = 16) {
213
+ const st = this.st;
214
+ const tmp = this.tmp0;
215
+ tmp[0] = (adLen * 8) & 0xffffffff;
216
+ tmp[1] = Math.floor((adLen * 8) / 0x100000000);
217
+ tmp[2] = (msgLen * 8) & 0xffffffff;
218
+ tmp[3] = Math.floor((msgLen * 8) / 0x100000000);
219
+ const unpacked = createAesBlocks();
220
+ unpacked.set(st);
221
+ unpack(unpacked);
222
+ tmp[0] = tmp[0] ^ unpacked[wordIdx(2, 0)];
223
+ tmp[1] = tmp[1] ^ unpacked[wordIdx(2, 1)];
224
+ tmp[2] = tmp[2] ^ unpacked[wordIdx(2, 2)];
225
+ tmp[3] = tmp[3] ^ unpacked[wordIdx(2, 3)];
226
+ packConstantInput128(this.constantInput, tmp, tmp);
239
227
  for (let i = 0; i < 7; i++) {
240
- this.update(t, t);
228
+ aegisRound128(st, this.constantInput);
241
229
  }
230
+ unpack(st);
242
231
  if (tagLen === 16) {
243
232
  const tag = new Uint8Array(16);
244
- for (let i = 0; i < 16; i++) {
245
- tag[i] =
246
- this.s0[i] ^
247
- this.s1[i] ^
248
- this.s2[i] ^
249
- this.s3[i] ^
250
- this.s4[i] ^
251
- this.s5[i] ^
252
- this.s6[i];
233
+ const tagBlock = createAesBlock();
234
+ for (let i = 0; i < 4; i++) {
235
+ tagBlock[i] =
236
+ st[wordIdx(0, i)] ^
237
+ st[wordIdx(1, i)] ^
238
+ st[wordIdx(2, i)] ^
239
+ st[wordIdx(3, i)] ^
240
+ st[wordIdx(4, i)] ^
241
+ st[wordIdx(5, i)] ^
242
+ st[wordIdx(6, i)];
253
243
  }
244
+ blockToBytes(tag, tagBlock);
254
245
  return tag;
255
246
  }
256
247
  else {
257
248
  const tag = new Uint8Array(32);
258
- for (let i = 0; i < 16; i++) {
259
- tag[i] = this.s0[i] ^ this.s1[i] ^ this.s2[i] ^ this.s3[i];
249
+ const tagBlock0 = createAesBlock();
250
+ const tagBlock1 = createAesBlock();
251
+ for (let i = 0; i < 4; i++) {
252
+ tagBlock0[i] =
253
+ st[wordIdx(0, i)] ^
254
+ st[wordIdx(1, i)] ^
255
+ st[wordIdx(2, i)] ^
256
+ st[wordIdx(3, i)];
260
257
  }
261
- for (let i = 0; i < 16; i++) {
262
- tag[16 + i] = this.s4[i] ^ this.s5[i] ^ this.s6[i] ^ this.s7[i];
258
+ for (let i = 0; i < 4; i++) {
259
+ tagBlock1[i] =
260
+ st[wordIdx(4, i)] ^
261
+ st[wordIdx(5, i)] ^
262
+ st[wordIdx(6, i)] ^
263
+ st[wordIdx(7, i)];
263
264
  }
265
+ blockToBytes(tag, tagBlock0);
266
+ blockToBytes(tag, tagBlock1, 16);
264
267
  return tag;
265
268
  }
266
269
  }
@@ -277,17 +280,21 @@ export class Aegis128LState {
277
280
  export function aegis128LEncryptDetached(msg, ad, key, nonce, tagLen = 16) {
278
281
  const state = new Aegis128LState();
279
282
  state.init(key, nonce);
280
- const adPadded = zeroPad(ad, 32);
281
- for (let i = 0; i + 32 <= adPadded.length; i += 32) {
282
- state.absorb(adPadded.subarray(i, i + 32));
283
+ const adPadded = zeroPad(ad, RATE);
284
+ for (let i = 0; i + RATE <= adPadded.length; i += RATE) {
285
+ state.absorb(adPadded, i);
286
+ }
287
+ const ciphertext = new Uint8Array(msg.length);
288
+ const fullBlocks = Math.floor(msg.length / RATE) * RATE;
289
+ for (let i = 0; i < fullBlocks; i += RATE) {
290
+ state.encTo(msg, ciphertext, i, i);
283
291
  }
284
- const msgPadded = zeroPad(msg, 32);
285
- const ct = new Uint8Array(msgPadded.length);
286
- for (let i = 0; i + 32 <= msgPadded.length; i += 32) {
287
- state.encTo(msgPadded.subarray(i, i + 32), ct.subarray(i, i + 32));
292
+ if (msg.length > fullBlocks) {
293
+ const lastBlock = zeroPad(msg.subarray(fullBlocks), RATE);
294
+ const encBlock = state.enc(lastBlock);
295
+ ciphertext.set(encBlock.subarray(0, msg.length - fullBlocks), fullBlocks);
288
296
  }
289
- const tag = state.finalize(BigInt(ad.length * 8), BigInt(msg.length * 8), tagLen);
290
- const ciphertext = new Uint8Array(ct.subarray(0, msg.length));
297
+ const tag = state.finalize(ad.length, msg.length, tagLen);
291
298
  return { ciphertext, tag };
292
299
  }
293
300
  /**
@@ -303,20 +310,19 @@ export function aegis128LDecryptDetached(ct, tag, ad, key, nonce) {
303
310
  const tagLen = tag.length;
304
311
  const state = new Aegis128LState();
305
312
  state.init(key, nonce);
306
- const adPadded = zeroPad(ad, 32);
307
- for (let i = 0; i + 32 <= adPadded.length; i += 32) {
308
- state.absorb(adPadded.subarray(i, i + 32));
313
+ const adPadded = zeroPad(ad, RATE);
314
+ for (let i = 0; i + RATE <= adPadded.length; i += RATE) {
315
+ state.absorb(adPadded, i);
309
316
  }
310
- const fullBlocksLen = Math.floor(ct.length / 32) * 32;
311
- const cn = ct.subarray(fullBlocksLen);
312
- const msg = new Uint8Array(fullBlocksLen + (cn.length > 0 ? cn.length : 0));
313
- for (let i = 0; i + 32 <= ct.length; i += 32) {
314
- state.decTo(ct.subarray(i, i + 32), msg.subarray(i, i + 32));
317
+ const msg = new Uint8Array(ct.length);
318
+ const fullBlocks = Math.floor(ct.length / RATE) * RATE;
319
+ for (let i = 0; i < fullBlocks; i += RATE) {
320
+ state.decTo(ct, msg, i, i);
315
321
  }
316
- if (cn.length > 0) {
317
- msg.set(state.decPartial(cn), fullBlocksLen);
322
+ if (ct.length > fullBlocks) {
323
+ msg.set(state.decPartial(ct.subarray(fullBlocks)), fullBlocks);
318
324
  }
319
- const expectedTag = state.finalize(BigInt(ad.length * 8), BigInt(msg.length * 8), tagLen);
325
+ const expectedTag = state.finalize(ad.length, msg.length, tagLen);
320
326
  if (!constantTimeEqual(tag, expectedTag)) {
321
327
  msg.fill(0);
322
328
  return null;
@@ -336,22 +342,22 @@ export function aegis128LDecryptDetached(ct, tag, ad, key, nonce) {
336
342
  export function aegis128LEncryptDetachedInPlace(data, ad, key, nonce, tagLen = 16) {
337
343
  const state = new Aegis128LState();
338
344
  state.init(key, nonce);
339
- const adPadded = zeroPad(ad, 32);
340
- for (let i = 0; i + 32 <= adPadded.length; i += 32) {
341
- state.absorb(adPadded.subarray(i, i + 32));
345
+ const adPadded = zeroPad(ad, RATE);
346
+ for (let i = 0; i + RATE <= adPadded.length; i += RATE) {
347
+ state.absorb(adPadded, i);
342
348
  }
343
349
  const msgLen = data.length;
344
- const fullBlocksLen = Math.floor(msgLen / 32) * 32;
345
- for (let i = 0; i < fullBlocksLen; i += 32) {
346
- state.encInPlace(data.subarray(i, i + 32));
350
+ const fullBlocksLen = Math.floor(msgLen / RATE) * RATE;
351
+ for (let i = 0; i < fullBlocksLen; i += RATE) {
352
+ state.encTo(data, data, i, i);
347
353
  }
348
354
  if (msgLen > fullBlocksLen) {
349
355
  const lastPartial = data.subarray(fullBlocksLen);
350
- const lastBlock = zeroPad(lastPartial, 32);
356
+ const lastBlock = zeroPad(lastPartial, RATE);
351
357
  const encBlock = state.enc(lastBlock);
352
358
  lastPartial.set(encBlock.subarray(0, lastPartial.length));
353
359
  }
354
- return state.finalize(BigInt(ad.length * 8), BigInt(msgLen * 8), tagLen);
360
+ return state.finalize(ad.length, msgLen, tagLen);
355
361
  }
356
362
  /**
357
363
  * Decrypts a message in-place using AEGIS-128L (detached mode).
@@ -367,21 +373,21 @@ export function aegis128LDecryptDetachedInPlace(data, tag, ad, key, nonce) {
367
373
  const tagLen = tag.length;
368
374
  const state = new Aegis128LState();
369
375
  state.init(key, nonce);
370
- const adPadded = zeroPad(ad, 32);
371
- for (let i = 0; i + 32 <= adPadded.length; i += 32) {
372
- state.absorb(adPadded.subarray(i, i + 32));
376
+ const adPadded = zeroPad(ad, RATE);
377
+ for (let i = 0; i + RATE <= adPadded.length; i += RATE) {
378
+ state.absorb(adPadded, i);
373
379
  }
374
380
  const msgLen = data.length;
375
- const fullBlocksLen = Math.floor(msgLen / 32) * 32;
376
- for (let i = 0; i < fullBlocksLen; i += 32) {
377
- state.decInPlace(data.subarray(i, i + 32));
381
+ const fullBlocksLen = Math.floor(msgLen / RATE) * RATE;
382
+ for (let i = 0; i < fullBlocksLen; i += RATE) {
383
+ state.decTo(data, data, i, i);
378
384
  }
379
385
  if (msgLen > fullBlocksLen) {
380
386
  const lastPartial = data.subarray(fullBlocksLen);
381
387
  const decrypted = state.decPartial(lastPartial);
382
388
  lastPartial.set(decrypted);
383
389
  }
384
- const expectedTag = state.finalize(BigInt(ad.length * 8), BigInt(msgLen * 8), tagLen);
390
+ const expectedTag = state.finalize(ad.length, msgLen, tagLen);
385
391
  if (!constantTimeEqual(tag, expectedTag)) {
386
392
  data.fill(0);
387
393
  return false;
@@ -404,26 +410,11 @@ export const AEGIS_128L_KEY_SIZE = 16;
404
410
  */
405
411
  export function aegis128LEncrypt(msg, ad, key, nonce = null, tagLen = 16) {
406
412
  const actualNonce = nonce ?? randomBytes(AEGIS_128L_NONCE_SIZE);
407
- const state = new Aegis128LState();
408
- state.init(key, actualNonce);
409
- const adPadded = zeroPad(ad, 32);
410
- for (let i = 0; i + 32 <= adPadded.length; i += 32) {
411
- state.absorb(adPadded.subarray(i, i + 32));
412
- }
413
- const nonceSize = AEGIS_128L_NONCE_SIZE;
414
- const result = new Uint8Array(nonceSize + msg.length + tagLen);
413
+ const { ciphertext, tag } = aegis128LEncryptDetached(msg, ad, key, actualNonce, tagLen);
414
+ const result = new Uint8Array(AEGIS_128L_NONCE_SIZE + ciphertext.length + tagLen);
415
415
  result.set(actualNonce, 0);
416
- const fullBlocks = Math.floor(msg.length / 32) * 32;
417
- for (let i = 0; i < fullBlocks; i += 32) {
418
- state.encTo(msg.subarray(i, i + 32), result.subarray(nonceSize + i, nonceSize + i + 32));
419
- }
420
- if (msg.length > fullBlocks) {
421
- const lastBlock = zeroPad(msg.subarray(fullBlocks), 32);
422
- const encBlock = state.enc(lastBlock);
423
- result.set(encBlock.subarray(0, msg.length - fullBlocks), nonceSize + fullBlocks);
424
- }
425
- const tag = state.finalize(BigInt(ad.length * 8), BigInt(msg.length * 8), tagLen);
426
- result.set(tag, nonceSize + msg.length);
416
+ result.set(ciphertext, AEGIS_128L_NONCE_SIZE);
417
+ result.set(tag, AEGIS_128L_NONCE_SIZE + ciphertext.length);
427
418
  return result;
428
419
  }
429
420
  /**
@@ -456,11 +447,11 @@ export function aegis128LDecrypt(sealed, ad, key, tagLen = 16) {
456
447
  export function aegis128LMac(data, key, nonce = null, tagLen = 16) {
457
448
  const state = new Aegis128LState();
458
449
  state.init(key, nonce ?? new Uint8Array(16));
459
- const dataPadded = zeroPad(data, 32);
460
- for (let i = 0; i + 32 <= dataPadded.length; i += 32) {
461
- state.absorb(dataPadded.subarray(i, i + 32));
450
+ const dataPadded = zeroPad(data, RATE);
451
+ for (let i = 0; i + RATE <= dataPadded.length; i += RATE) {
452
+ state.absorb(dataPadded, i);
462
453
  }
463
- return state.finalize(BigInt(data.length * 8), BigInt(tagLen * 8), tagLen);
454
+ return state.finalize(data.length, tagLen, tagLen);
464
455
  }
465
456
  /**
466
457
  * Verifies a MAC computed using AEGIS-128L.
@@ -491,4 +482,3 @@ export function aegis128LCreateKey() {
491
482
  export function aegis128LCreateNonce() {
492
483
  return randomBytes(AEGIS_128L_NONCE_SIZE);
493
484
  }
494
- //# sourceMappingURL=aegis128l.js.map