aegis-aead 0.2.2 → 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.
- package/README.md +25 -20
- package/dist/aegis128l.d.ts +33 -33
- package/dist/aegis128l.js +225 -235
- package/dist/aegis128x.d.ts +35 -35
- package/dist/aegis128x.js +348 -282
- package/dist/aegis256.d.ts +34 -51
- package/dist/aegis256.js +215 -206
- package/dist/aegis256x.d.ts +32 -33
- package/dist/aegis256x.js +333 -265
- package/dist/aes-bs.d.ts +42 -35
- package/dist/aes-bs.js +2269 -401
- package/dist/index.d.ts +4 -7
- package/dist/index.js +4 -7
- package/dist/random.d.ts +0 -1
- package/dist/random.js +0 -1
- package/dist/utils.d.ts +14 -0
- package/dist/utils.js +31 -0
- package/package.json +5 -6
- package/dist/aegis128l-bs.d.ts +0 -137
- package/dist/aegis128l-bs.d.ts.map +0 -1
- package/dist/aegis128l-bs.js +0 -442
- package/dist/aegis128l-bs.js.map +0 -1
- package/dist/aegis128l.d.ts.map +0 -1
- package/dist/aegis128l.js.map +0 -1
- package/dist/aegis128x.d.ts.map +0 -1
- package/dist/aegis128x.js.map +0 -1
- package/dist/aegis256-bs.d.ts +0 -79
- package/dist/aegis256-bs.d.ts.map +0 -1
- package/dist/aegis256-bs.js +0 -366
- package/dist/aegis256-bs.js.map +0 -1
- package/dist/aegis256.d.ts.map +0 -1
- package/dist/aegis256.js.map +0 -1
- package/dist/aegis256x.d.ts.map +0 -1
- package/dist/aegis256x.js.map +0 -1
- package/dist/aes-bs.d.ts.map +0 -1
- package/dist/aes-bs.js.map +0 -1
- package/dist/aes.d.ts +0 -81
- package/dist/aes.d.ts.map +0 -1
- package/dist/aes.js +0 -232
- package/dist/aes.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/random.d.ts.map +0 -1
- package/dist/random.js.map +0 -1
- package/src/aegis128l-bs.ts +0 -600
- package/src/aegis128l.ts +0 -653
- package/src/aegis128x.ts +0 -932
- package/src/aegis256-bs.ts +0 -519
- package/src/aegis256.ts +0 -597
- package/src/aegis256x.ts +0 -893
- package/src/aes-bs.ts +0 -540
- package/src/aes.ts +0 -271
- package/src/index.ts +0 -126
- package/src/random.ts +0 -41
- package/src/typed-array.d.ts +0 -18
package/src/aegis128x.ts
DELETED
|
@@ -1,932 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
aesRoundTo,
|
|
3
|
-
andBlocksTo,
|
|
4
|
-
C0,
|
|
5
|
-
C1,
|
|
6
|
-
concatBytes,
|
|
7
|
-
constantTimeEqual,
|
|
8
|
-
le64,
|
|
9
|
-
xorBlocks,
|
|
10
|
-
xorBlocksTo,
|
|
11
|
-
zeroPad,
|
|
12
|
-
} from "./aes.js";
|
|
13
|
-
import { randomBytes } from "./random.js";
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* AEGIS-128X cipher state with configurable parallelism degree.
|
|
17
|
-
* Extends AEGIS-128L with parallel AES rounds for improved performance on wide SIMD architectures.
|
|
18
|
-
*/
|
|
19
|
-
export class Aegis128XState {
|
|
20
|
-
private v: Uint8Array[][];
|
|
21
|
-
private d: number;
|
|
22
|
-
private rate: number;
|
|
23
|
-
private newV: Uint8Array[][];
|
|
24
|
-
private tmp: Uint8Array;
|
|
25
|
-
private z0: Uint8Array;
|
|
26
|
-
private z1: Uint8Array;
|
|
27
|
-
private ctxBufs: Uint8Array[];
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Creates a new AEGIS-128X state.
|
|
31
|
-
* @param degree - Parallelism degree (default: 2). Use 2 for AEGIS-128X2, 4 for AEGIS-128X4.
|
|
32
|
-
*/
|
|
33
|
-
constructor(degree: number = 2) {
|
|
34
|
-
this.d = degree;
|
|
35
|
-
this.rate = 256 * degree;
|
|
36
|
-
this.v = Array.from({ length: 8 }, () =>
|
|
37
|
-
Array.from({ length: degree }, () => new Uint8Array(16)),
|
|
38
|
-
);
|
|
39
|
-
this.newV = Array.from({ length: 8 }, () =>
|
|
40
|
-
Array.from({ length: degree }, () => new Uint8Array(16)),
|
|
41
|
-
);
|
|
42
|
-
this.tmp = new Uint8Array(16);
|
|
43
|
-
this.z0 = new Uint8Array(16 * degree);
|
|
44
|
-
this.z1 = new Uint8Array(16 * degree);
|
|
45
|
-
this.ctxBufs = Array.from({ length: degree }, (_, i) => {
|
|
46
|
-
const buf = new Uint8Array(16);
|
|
47
|
-
buf[0] = i;
|
|
48
|
-
buf[1] = degree - 1;
|
|
49
|
-
return buf;
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Initializes the state with a key and nonce.
|
|
55
|
-
* @param key - 16-byte encryption key
|
|
56
|
-
* @param nonce - 16-byte nonce (must be unique per message)
|
|
57
|
-
*/
|
|
58
|
-
init(key: Uint8Array, nonce: Uint8Array): void {
|
|
59
|
-
const keyXorNonce = new Uint8Array(16);
|
|
60
|
-
const keyXorC0 = new Uint8Array(16);
|
|
61
|
-
const keyXorC1 = new Uint8Array(16);
|
|
62
|
-
xorBlocksTo(key, nonce, keyXorNonce);
|
|
63
|
-
xorBlocksTo(key, C0, keyXorC0);
|
|
64
|
-
xorBlocksTo(key, C1, keyXorC1);
|
|
65
|
-
|
|
66
|
-
for (let i = 0; i < this.d; i++) {
|
|
67
|
-
this.v[0]![i]!.set(keyXorNonce);
|
|
68
|
-
this.v[1]![i]!.set(C1);
|
|
69
|
-
this.v[2]![i]!.set(C0);
|
|
70
|
-
this.v[3]![i]!.set(C1);
|
|
71
|
-
this.v[4]![i]!.set(keyXorNonce);
|
|
72
|
-
this.v[5]![i]!.set(keyXorC0);
|
|
73
|
-
this.v[6]![i]!.set(keyXorC1);
|
|
74
|
-
this.v[7]![i]!.set(keyXorC0);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const nonceV = new Uint8Array(16 * this.d);
|
|
78
|
-
const keyV = new Uint8Array(16 * this.d);
|
|
79
|
-
for (let i = 0; i < this.d; i++) {
|
|
80
|
-
nonceV.set(nonce, i * 16);
|
|
81
|
-
keyV.set(key, i * 16);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
for (let round = 0; round < 10; round++) {
|
|
85
|
-
for (let i = 0; i < this.d; i++) {
|
|
86
|
-
const ctx = this.ctxBufs[i]!;
|
|
87
|
-
for (let j = 0; j < 16; j++) this.v[3]![i]![j] ^= ctx[j]!;
|
|
88
|
-
for (let j = 0; j < 16; j++) this.v[7]![i]![j] ^= ctx[j]!;
|
|
89
|
-
}
|
|
90
|
-
this.update(nonceV, keyV);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Updates the state with two message vectors.
|
|
96
|
-
* @param m0 - First message vector (16*degree bytes)
|
|
97
|
-
* @param m1 - Second message vector (16*degree bytes)
|
|
98
|
-
*/
|
|
99
|
-
update(m0: Uint8Array, m1: Uint8Array): void {
|
|
100
|
-
const newV = this.newV;
|
|
101
|
-
const tmp = this.tmp;
|
|
102
|
-
|
|
103
|
-
for (let i = 0; i < this.d; i++) {
|
|
104
|
-
const m0i = m0.subarray(i * 16, (i + 1) * 16);
|
|
105
|
-
const m1i = m1.subarray(i * 16, (i + 1) * 16);
|
|
106
|
-
|
|
107
|
-
xorBlocksTo(this.v[0]![i]!, m0i, tmp);
|
|
108
|
-
aesRoundTo(this.v[7]![i]!, tmp, newV[0]![i]!);
|
|
109
|
-
aesRoundTo(this.v[0]![i]!, this.v[1]![i]!, newV[1]![i]!);
|
|
110
|
-
aesRoundTo(this.v[1]![i]!, this.v[2]![i]!, newV[2]![i]!);
|
|
111
|
-
aesRoundTo(this.v[2]![i]!, this.v[3]![i]!, newV[3]![i]!);
|
|
112
|
-
xorBlocksTo(this.v[4]![i]!, m1i, tmp);
|
|
113
|
-
aesRoundTo(this.v[3]![i]!, tmp, newV[4]![i]!);
|
|
114
|
-
aesRoundTo(this.v[4]![i]!, this.v[5]![i]!, newV[5]![i]!);
|
|
115
|
-
aesRoundTo(this.v[5]![i]!, this.v[6]![i]!, newV[6]![i]!);
|
|
116
|
-
aesRoundTo(this.v[6]![i]!, this.v[7]![i]!, newV[7]![i]!);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
for (let j = 0; j < 8; j++) {
|
|
120
|
-
for (let i = 0; i < this.d; i++) {
|
|
121
|
-
this.v[j]![i]!.set(newV[j]![i]!);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Absorbs an associated data block into the state.
|
|
128
|
-
* @param ai - Associated data block (32*degree bytes)
|
|
129
|
-
*/
|
|
130
|
-
absorb(ai: Uint8Array): void {
|
|
131
|
-
const halfRateBytes = this.rate / 16;
|
|
132
|
-
const rateBytes = this.rate / 8;
|
|
133
|
-
this.update(
|
|
134
|
-
ai.subarray(0, halfRateBytes),
|
|
135
|
-
ai.subarray(halfRateBytes, rateBytes),
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private computeZ(): void {
|
|
140
|
-
const z0 = this.z0;
|
|
141
|
-
const z1 = this.z1;
|
|
142
|
-
const tmp = this.tmp;
|
|
143
|
-
|
|
144
|
-
for (let i = 0; i < this.d; i++) {
|
|
145
|
-
const off = i * 16;
|
|
146
|
-
xorBlocksTo(this.v[6]![i]!, this.v[1]![i]!, z0.subarray(off, off + 16));
|
|
147
|
-
andBlocksTo(this.v[2]![i]!, this.v[3]![i]!, tmp);
|
|
148
|
-
for (let j = 0; j < 16; j++) z0[off + j] ^= tmp[j]!;
|
|
149
|
-
|
|
150
|
-
xorBlocksTo(this.v[2]![i]!, this.v[5]![i]!, z1.subarray(off, off + 16));
|
|
151
|
-
andBlocksTo(this.v[6]![i]!, this.v[7]![i]!, tmp);
|
|
152
|
-
for (let j = 0; j < 16; j++) z1[off + j] ^= tmp[j]!;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Encrypts a plaintext block and writes to output buffer.
|
|
158
|
-
* @param xi - Plaintext block (32*degree bytes)
|
|
159
|
-
* @param out - Output buffer (32*degree bytes)
|
|
160
|
-
*/
|
|
161
|
-
encTo(xi: Uint8Array, out: Uint8Array): void {
|
|
162
|
-
this.computeZ();
|
|
163
|
-
const z0 = this.z0;
|
|
164
|
-
const z1 = this.z1;
|
|
165
|
-
|
|
166
|
-
const halfRateBytes = this.rate / 16;
|
|
167
|
-
const rateBytes = this.rate / 8;
|
|
168
|
-
const t0 = xi.subarray(0, halfRateBytes);
|
|
169
|
-
const t1 = xi.subarray(halfRateBytes, rateBytes);
|
|
170
|
-
|
|
171
|
-
for (let i = 0; i < halfRateBytes; i++) out[i] = t0[i]! ^ z0[i]!;
|
|
172
|
-
for (let i = 0; i < halfRateBytes; i++)
|
|
173
|
-
out[halfRateBytes + i] = t1[i]! ^ z1[i]!;
|
|
174
|
-
|
|
175
|
-
this.update(t0, t1);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Encrypts a plaintext block.
|
|
180
|
-
* @param xi - Plaintext block (32*degree bytes)
|
|
181
|
-
* @returns Ciphertext block of the same size
|
|
182
|
-
*/
|
|
183
|
-
enc(xi: Uint8Array): Uint8Array {
|
|
184
|
-
const rateBytes = this.rate / 8;
|
|
185
|
-
const out = new Uint8Array(rateBytes);
|
|
186
|
-
this.encTo(xi, out);
|
|
187
|
-
return out;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Decrypts a ciphertext block and writes to output buffer.
|
|
192
|
-
* @param ci - Ciphertext block (32*degree bytes)
|
|
193
|
-
* @param out - Output buffer (32*degree bytes)
|
|
194
|
-
*/
|
|
195
|
-
decTo(ci: Uint8Array, out: Uint8Array): void {
|
|
196
|
-
this.computeZ();
|
|
197
|
-
const z0 = this.z0;
|
|
198
|
-
const z1 = this.z1;
|
|
199
|
-
|
|
200
|
-
const halfRateBytes = this.rate / 16;
|
|
201
|
-
const rateBytes = this.rate / 8;
|
|
202
|
-
const t0 = ci.subarray(0, halfRateBytes);
|
|
203
|
-
const t1 = ci.subarray(halfRateBytes, rateBytes);
|
|
204
|
-
|
|
205
|
-
for (let i = 0; i < halfRateBytes; i++) out[i] = t0[i]! ^ z0[i]!;
|
|
206
|
-
for (let i = 0; i < halfRateBytes; i++)
|
|
207
|
-
out[halfRateBytes + i] = t1[i]! ^ z1[i]!;
|
|
208
|
-
|
|
209
|
-
this.update(
|
|
210
|
-
out.subarray(0, halfRateBytes),
|
|
211
|
-
out.subarray(halfRateBytes, rateBytes),
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Decrypts a ciphertext block.
|
|
217
|
-
* @param ci - Ciphertext block (32*degree bytes)
|
|
218
|
-
* @returns Plaintext block of the same size
|
|
219
|
-
*/
|
|
220
|
-
dec(ci: Uint8Array): Uint8Array {
|
|
221
|
-
const rateBytes = this.rate / 8;
|
|
222
|
-
const out = new Uint8Array(rateBytes);
|
|
223
|
-
this.decTo(ci, out);
|
|
224
|
-
return out;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Encrypts a plaintext block in-place.
|
|
229
|
-
* @param block - Buffer (plaintext in, ciphertext out), size 32*degree bytes
|
|
230
|
-
*/
|
|
231
|
-
encInPlace(block: Uint8Array): void {
|
|
232
|
-
this.computeZ();
|
|
233
|
-
const z0 = this.z0;
|
|
234
|
-
const z1 = this.z1;
|
|
235
|
-
|
|
236
|
-
const halfRateBytes = this.rate / 16;
|
|
237
|
-
const rateBytes = this.rate / 8;
|
|
238
|
-
|
|
239
|
-
this.update(
|
|
240
|
-
block.subarray(0, halfRateBytes),
|
|
241
|
-
block.subarray(halfRateBytes, rateBytes),
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
for (let i = 0; i < halfRateBytes; i++) block[i] ^= z0[i]!;
|
|
245
|
-
for (let i = 0; i < halfRateBytes; i++) block[halfRateBytes + i] ^= z1[i]!;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Decrypts a ciphertext block in-place.
|
|
250
|
-
* @param block - Buffer (ciphertext in, plaintext out), size 32*degree bytes
|
|
251
|
-
*/
|
|
252
|
-
decInPlace(block: Uint8Array): void {
|
|
253
|
-
this.decTo(block, block);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
/**
|
|
257
|
-
* Decrypts a partial (final) ciphertext block.
|
|
258
|
-
* @param cn - Partial ciphertext block (smaller than 32*degree bytes)
|
|
259
|
-
* @returns Decrypted plaintext of the same length
|
|
260
|
-
*/
|
|
261
|
-
decPartial(cn: Uint8Array): Uint8Array {
|
|
262
|
-
this.computeZ();
|
|
263
|
-
const z0 = this.z0;
|
|
264
|
-
const z1 = this.z1;
|
|
265
|
-
|
|
266
|
-
const rateBytes = this.rate / 8;
|
|
267
|
-
const halfRateBytes = rateBytes / 2;
|
|
268
|
-
const padded = zeroPad(cn, rateBytes);
|
|
269
|
-
const t0 = padded.subarray(0, halfRateBytes);
|
|
270
|
-
const t1 = padded.subarray(halfRateBytes, rateBytes);
|
|
271
|
-
|
|
272
|
-
const out = new Uint8Array(rateBytes);
|
|
273
|
-
for (let i = 0; i < halfRateBytes; i++) out[i] = t0[i]! ^ z0[i]!;
|
|
274
|
-
for (let i = 0; i < halfRateBytes; i++)
|
|
275
|
-
out[halfRateBytes + i] = t1[i]! ^ z1[i]!;
|
|
276
|
-
|
|
277
|
-
const xn = new Uint8Array(out.subarray(0, cn.length));
|
|
278
|
-
|
|
279
|
-
const v = zeroPad(xn, rateBytes);
|
|
280
|
-
this.update(
|
|
281
|
-
v.subarray(0, halfRateBytes),
|
|
282
|
-
v.subarray(halfRateBytes, rateBytes),
|
|
283
|
-
);
|
|
284
|
-
|
|
285
|
-
return xn;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* Finalizes encryption/decryption and produces an authentication tag.
|
|
290
|
-
* @param adLenBits - Associated data length in bits
|
|
291
|
-
* @param msgLenBits - Message length in bits
|
|
292
|
-
* @param tagLen - Tag length (16 or 32 bytes)
|
|
293
|
-
* @returns Authentication tag
|
|
294
|
-
*/
|
|
295
|
-
finalize(
|
|
296
|
-
adLenBits: bigint,
|
|
297
|
-
msgLenBits: bigint,
|
|
298
|
-
tagLen: 16 | 32 = 16,
|
|
299
|
-
): Uint8Array {
|
|
300
|
-
let t = new Uint8Array(0);
|
|
301
|
-
const u = concatBytes(le64(adLenBits), le64(msgLenBits));
|
|
302
|
-
|
|
303
|
-
for (let i = 0; i < this.d; i++) {
|
|
304
|
-
t = concatBytes(t, xorBlocks(this.v[2]![i]!, u));
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
for (let round = 0; round < 7; round++) {
|
|
308
|
-
this.update(t, t);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (tagLen === 16) {
|
|
312
|
-
let tag = new Uint8Array(16);
|
|
313
|
-
for (let i = 0; i < this.d; i++) {
|
|
314
|
-
let ti = xorBlocks(this.v[0]![i]!, this.v[1]![i]!);
|
|
315
|
-
ti = xorBlocks(ti, this.v[2]![i]!);
|
|
316
|
-
ti = xorBlocks(ti, this.v[3]![i]!);
|
|
317
|
-
ti = xorBlocks(ti, this.v[4]![i]!);
|
|
318
|
-
ti = xorBlocks(ti, this.v[5]![i]!);
|
|
319
|
-
ti = xorBlocks(ti, this.v[6]![i]!);
|
|
320
|
-
tag = xorBlocks(tag, ti);
|
|
321
|
-
}
|
|
322
|
-
return tag;
|
|
323
|
-
} else {
|
|
324
|
-
let ti0 = new Uint8Array(16);
|
|
325
|
-
let ti1 = new Uint8Array(16);
|
|
326
|
-
for (let i = 0; i < this.d; i++) {
|
|
327
|
-
ti0 = xorBlocks(ti0, this.v[0]![i]!);
|
|
328
|
-
ti0 = xorBlocks(ti0, this.v[1]![i]!);
|
|
329
|
-
ti0 = xorBlocks(ti0, this.v[2]![i]!);
|
|
330
|
-
ti0 = xorBlocks(ti0, this.v[3]![i]!);
|
|
331
|
-
ti1 = xorBlocks(ti1, this.v[4]![i]!);
|
|
332
|
-
ti1 = xorBlocks(ti1, this.v[5]![i]!);
|
|
333
|
-
ti1 = xorBlocks(ti1, this.v[6]![i]!);
|
|
334
|
-
ti1 = xorBlocks(ti1, this.v[7]![i]!);
|
|
335
|
-
}
|
|
336
|
-
return concatBytes(ti0, ti1);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Finalizes MAC computation and produces an authentication tag.
|
|
342
|
-
* Uses a different finalization procedure than encryption/decryption.
|
|
343
|
-
* @param dataLenBits - Data length in bits
|
|
344
|
-
* @param tagLen - Tag length (16 or 32 bytes)
|
|
345
|
-
* @returns Authentication tag
|
|
346
|
-
*/
|
|
347
|
-
finalizeMac(dataLenBits: bigint, tagLen: 16 | 32 = 16): Uint8Array {
|
|
348
|
-
let t = new Uint8Array(0);
|
|
349
|
-
const u = concatBytes(le64(dataLenBits), le64(BigInt(tagLen * 8)));
|
|
350
|
-
|
|
351
|
-
for (let i = 0; i < this.d; i++) {
|
|
352
|
-
t = concatBytes(t, xorBlocks(this.v[2]![i]!, u));
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
for (let round = 0; round < 7; round++) {
|
|
356
|
-
this.update(t, t);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
let tags = new Uint8Array(0);
|
|
360
|
-
if (tagLen === 16) {
|
|
361
|
-
for (let i = 0; i < this.d; i++) {
|
|
362
|
-
let ti = xorBlocks(this.v[0]![i]!, this.v[1]![i]!);
|
|
363
|
-
ti = xorBlocks(ti, this.v[2]![i]!);
|
|
364
|
-
ti = xorBlocks(ti, this.v[3]![i]!);
|
|
365
|
-
ti = xorBlocks(ti, this.v[4]![i]!);
|
|
366
|
-
ti = xorBlocks(ti, this.v[5]![i]!);
|
|
367
|
-
ti = xorBlocks(ti, this.v[6]![i]!);
|
|
368
|
-
tags = concatBytes(tags, ti);
|
|
369
|
-
}
|
|
370
|
-
} else {
|
|
371
|
-
for (let i = 1; i < this.d; i++) {
|
|
372
|
-
let ti0 = xorBlocks(this.v[0]![i]!, this.v[1]![i]!);
|
|
373
|
-
ti0 = xorBlocks(ti0, this.v[2]![i]!);
|
|
374
|
-
ti0 = xorBlocks(ti0, this.v[3]![i]!);
|
|
375
|
-
let ti1 = xorBlocks(this.v[4]![i]!, this.v[5]![i]!);
|
|
376
|
-
ti1 = xorBlocks(ti1, this.v[6]![i]!);
|
|
377
|
-
ti1 = xorBlocks(ti1, this.v[7]![i]!);
|
|
378
|
-
tags = concatBytes(tags, ti0, ti1);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
if (this.d > 1) {
|
|
383
|
-
for (let i = 0; i + 32 <= tags.length; i += 32) {
|
|
384
|
-
const tb = tags.subarray(i, i + 32);
|
|
385
|
-
const x0 = zeroPad(tb.subarray(0, 16), 16 * this.d);
|
|
386
|
-
const x1 = zeroPad(tb.subarray(16, 32), 16 * this.d);
|
|
387
|
-
this.absorb(concatBytes(x0, x1));
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
const u2 = concatBytes(le64(BigInt(this.d)), le64(BigInt(tagLen * 8)));
|
|
391
|
-
const t2 = zeroPad(xorBlocks(this.v[2]![0]!, u2), this.rate / 8);
|
|
392
|
-
for (let round = 0; round < 7; round++) {
|
|
393
|
-
this.update(t2, t2);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
if (tagLen === 16) {
|
|
398
|
-
let tag = xorBlocks(this.v[0]![0]!, this.v[1]![0]!);
|
|
399
|
-
tag = xorBlocks(tag, this.v[2]![0]!);
|
|
400
|
-
tag = xorBlocks(tag, this.v[3]![0]!);
|
|
401
|
-
tag = xorBlocks(tag, this.v[4]![0]!);
|
|
402
|
-
tag = xorBlocks(tag, this.v[5]![0]!);
|
|
403
|
-
tag = xorBlocks(tag, this.v[6]![0]!);
|
|
404
|
-
return tag;
|
|
405
|
-
} else {
|
|
406
|
-
let t0 = xorBlocks(this.v[0]![0]!, this.v[1]![0]!);
|
|
407
|
-
t0 = xorBlocks(t0, this.v[2]![0]!);
|
|
408
|
-
t0 = xorBlocks(t0, this.v[3]![0]!);
|
|
409
|
-
let t1 = xorBlocks(this.v[4]![0]!, this.v[5]![0]!);
|
|
410
|
-
t1 = xorBlocks(t1, this.v[6]![0]!);
|
|
411
|
-
t1 = xorBlocks(t1, this.v[7]![0]!);
|
|
412
|
-
return concatBytes(t0, t1);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* Encrypts a message using AEGIS-128X (detached mode).
|
|
419
|
-
* @param msg - Plaintext message
|
|
420
|
-
* @param ad - Associated data (authenticated but not encrypted)
|
|
421
|
-
* @param key - 16-byte encryption key
|
|
422
|
-
* @param nonce - 16-byte nonce (must be unique per message with the same key)
|
|
423
|
-
* @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
|
|
424
|
-
* @param degree - Parallelism degree (default: 2)
|
|
425
|
-
* @returns Object containing ciphertext and authentication tag separately
|
|
426
|
-
*/
|
|
427
|
-
export function aegis128XEncryptDetached(
|
|
428
|
-
msg: Uint8Array,
|
|
429
|
-
ad: Uint8Array,
|
|
430
|
-
key: Uint8Array,
|
|
431
|
-
nonce: Uint8Array,
|
|
432
|
-
tagLen: 16 | 32 = 16,
|
|
433
|
-
degree: number = 2,
|
|
434
|
-
): { ciphertext: Uint8Array; tag: Uint8Array } {
|
|
435
|
-
const state = new Aegis128XState(degree);
|
|
436
|
-
const rateBytes = (256 * degree) / 8;
|
|
437
|
-
|
|
438
|
-
state.init(key, nonce);
|
|
439
|
-
|
|
440
|
-
const adPadded = zeroPad(ad, rateBytes);
|
|
441
|
-
for (let i = 0; i + rateBytes <= adPadded.length; i += rateBytes) {
|
|
442
|
-
state.absorb(adPadded.subarray(i, i + rateBytes));
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
const msgPadded = zeroPad(msg, rateBytes);
|
|
446
|
-
const ct = new Uint8Array(msgPadded.length);
|
|
447
|
-
for (let i = 0; i + rateBytes <= msgPadded.length; i += rateBytes) {
|
|
448
|
-
state.encTo(
|
|
449
|
-
msgPadded.subarray(i, i + rateBytes),
|
|
450
|
-
ct.subarray(i, i + rateBytes),
|
|
451
|
-
);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
const tag = state.finalize(
|
|
455
|
-
BigInt(ad.length * 8),
|
|
456
|
-
BigInt(msg.length * 8),
|
|
457
|
-
tagLen,
|
|
458
|
-
);
|
|
459
|
-
const ciphertext = new Uint8Array(ct.subarray(0, msg.length));
|
|
460
|
-
|
|
461
|
-
return { ciphertext, tag };
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
/**
|
|
465
|
-
* Decrypts a message using AEGIS-128X (detached mode).
|
|
466
|
-
* @param ct - Ciphertext
|
|
467
|
-
* @param tag - Authentication tag (16 or 32 bytes)
|
|
468
|
-
* @param ad - Associated data (must match what was used during encryption)
|
|
469
|
-
* @param key - 16-byte encryption key
|
|
470
|
-
* @param nonce - 16-byte nonce (must match what was used during encryption)
|
|
471
|
-
* @param degree - Parallelism degree (default: 2)
|
|
472
|
-
* @returns Decrypted plaintext, or null if authentication fails
|
|
473
|
-
*/
|
|
474
|
-
export function aegis128XDecryptDetached(
|
|
475
|
-
ct: Uint8Array,
|
|
476
|
-
tag: Uint8Array,
|
|
477
|
-
ad: Uint8Array,
|
|
478
|
-
key: Uint8Array,
|
|
479
|
-
nonce: Uint8Array,
|
|
480
|
-
degree: number = 2,
|
|
481
|
-
): Uint8Array | null {
|
|
482
|
-
const tagLen = tag.length as 16 | 32;
|
|
483
|
-
const state = new Aegis128XState(degree);
|
|
484
|
-
const rateBytes = (256 * degree) / 8;
|
|
485
|
-
|
|
486
|
-
state.init(key, nonce);
|
|
487
|
-
|
|
488
|
-
const adPadded = zeroPad(ad, rateBytes);
|
|
489
|
-
for (let i = 0; i + rateBytes <= adPadded.length; i += rateBytes) {
|
|
490
|
-
state.absorb(adPadded.subarray(i, i + rateBytes));
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
const fullBlocksLen = Math.floor(ct.length / rateBytes) * rateBytes;
|
|
494
|
-
const cn = ct.subarray(fullBlocksLen);
|
|
495
|
-
|
|
496
|
-
const msg = new Uint8Array(fullBlocksLen + (cn.length > 0 ? cn.length : 0));
|
|
497
|
-
for (let i = 0; i + rateBytes <= ct.length; i += rateBytes) {
|
|
498
|
-
state.decTo(ct.subarray(i, i + rateBytes), msg.subarray(i, i + rateBytes));
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
if (cn.length > 0) {
|
|
502
|
-
msg.set(state.decPartial(cn), fullBlocksLen);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
const expectedTag = state.finalize(
|
|
506
|
-
BigInt(ad.length * 8),
|
|
507
|
-
BigInt(msg.length * 8),
|
|
508
|
-
tagLen,
|
|
509
|
-
);
|
|
510
|
-
|
|
511
|
-
if (!constantTimeEqual(tag, expectedTag)) {
|
|
512
|
-
msg.fill(0);
|
|
513
|
-
return null;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
return msg;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Encrypts a message in-place using AEGIS-128X (detached mode).
|
|
521
|
-
* The input buffer is modified to contain the ciphertext.
|
|
522
|
-
* @param data - Buffer containing plaintext (will be overwritten with ciphertext)
|
|
523
|
-
* @param ad - Associated data (authenticated but not encrypted)
|
|
524
|
-
* @param key - 16-byte encryption key
|
|
525
|
-
* @param nonce - 16-byte nonce (must be unique per message with the same key)
|
|
526
|
-
* @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
|
|
527
|
-
* @param degree - Parallelism degree (default: 2)
|
|
528
|
-
* @returns Authentication tag
|
|
529
|
-
*/
|
|
530
|
-
export function aegis128XEncryptDetachedInPlace(
|
|
531
|
-
data: Uint8Array,
|
|
532
|
-
ad: Uint8Array,
|
|
533
|
-
key: Uint8Array,
|
|
534
|
-
nonce: Uint8Array,
|
|
535
|
-
tagLen: 16 | 32 = 16,
|
|
536
|
-
degree: number = 2,
|
|
537
|
-
): Uint8Array {
|
|
538
|
-
const state = new Aegis128XState(degree);
|
|
539
|
-
const rateBytes = (256 * degree) / 8;
|
|
540
|
-
|
|
541
|
-
state.init(key, nonce);
|
|
542
|
-
|
|
543
|
-
const adPadded = zeroPad(ad, rateBytes);
|
|
544
|
-
for (let i = 0; i + rateBytes <= adPadded.length; i += rateBytes) {
|
|
545
|
-
state.absorb(adPadded.subarray(i, i + rateBytes));
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
const msgLen = data.length;
|
|
549
|
-
const fullBlocksLen = Math.floor(msgLen / rateBytes) * rateBytes;
|
|
550
|
-
|
|
551
|
-
for (let i = 0; i < fullBlocksLen; i += rateBytes) {
|
|
552
|
-
state.encInPlace(data.subarray(i, i + rateBytes));
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
if (msgLen > fullBlocksLen) {
|
|
556
|
-
const lastPartial = data.subarray(fullBlocksLen);
|
|
557
|
-
const lastBlock = zeroPad(lastPartial, rateBytes);
|
|
558
|
-
const encBlock = state.enc(lastBlock);
|
|
559
|
-
lastPartial.set(encBlock.subarray(0, lastPartial.length));
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
return state.finalize(BigInt(ad.length * 8), BigInt(msgLen * 8), tagLen);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
/**
|
|
566
|
-
* Decrypts a message in-place using AEGIS-128X (detached mode).
|
|
567
|
-
* The input buffer is modified to contain the plaintext (or zeroed on failure).
|
|
568
|
-
* @param data - Buffer containing ciphertext (will be overwritten with plaintext)
|
|
569
|
-
* @param tag - Authentication tag (16 or 32 bytes)
|
|
570
|
-
* @param ad - Associated data (must match what was used during encryption)
|
|
571
|
-
* @param key - 16-byte encryption key
|
|
572
|
-
* @param nonce - 16-byte nonce (must match what was used during encryption)
|
|
573
|
-
* @param degree - Parallelism degree (default: 2)
|
|
574
|
-
* @returns True if authentication succeeds, false otherwise
|
|
575
|
-
*/
|
|
576
|
-
export function aegis128XDecryptDetachedInPlace(
|
|
577
|
-
data: Uint8Array,
|
|
578
|
-
tag: Uint8Array,
|
|
579
|
-
ad: Uint8Array,
|
|
580
|
-
key: Uint8Array,
|
|
581
|
-
nonce: Uint8Array,
|
|
582
|
-
degree: number = 2,
|
|
583
|
-
): boolean {
|
|
584
|
-
const tagLen = tag.length as 16 | 32;
|
|
585
|
-
const state = new Aegis128XState(degree);
|
|
586
|
-
const rateBytes = (256 * degree) / 8;
|
|
587
|
-
|
|
588
|
-
state.init(key, nonce);
|
|
589
|
-
|
|
590
|
-
const adPadded = zeroPad(ad, rateBytes);
|
|
591
|
-
for (let i = 0; i + rateBytes <= adPadded.length; i += rateBytes) {
|
|
592
|
-
state.absorb(adPadded.subarray(i, i + rateBytes));
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
const msgLen = data.length;
|
|
596
|
-
const fullBlocksLen = Math.floor(msgLen / rateBytes) * rateBytes;
|
|
597
|
-
|
|
598
|
-
for (let i = 0; i < fullBlocksLen; i += rateBytes) {
|
|
599
|
-
state.decInPlace(data.subarray(i, i + rateBytes));
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
if (msgLen > fullBlocksLen) {
|
|
603
|
-
const lastPartial = data.subarray(fullBlocksLen);
|
|
604
|
-
const decrypted = state.decPartial(lastPartial);
|
|
605
|
-
lastPartial.set(decrypted);
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
const expectedTag = state.finalize(
|
|
609
|
-
BigInt(ad.length * 8),
|
|
610
|
-
BigInt(msgLen * 8),
|
|
611
|
-
tagLen,
|
|
612
|
-
);
|
|
613
|
-
|
|
614
|
-
if (!constantTimeEqual(tag, expectedTag)) {
|
|
615
|
-
data.fill(0);
|
|
616
|
-
return false;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
return true;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
/** AEGIS-128X2 in-place encryption - detached mode (degree=2). */
|
|
623
|
-
export const aegis128X2EncryptDetachedInPlace = (
|
|
624
|
-
data: Uint8Array,
|
|
625
|
-
ad: Uint8Array,
|
|
626
|
-
key: Uint8Array,
|
|
627
|
-
nonce: Uint8Array,
|
|
628
|
-
tagLen: 16 | 32 = 16,
|
|
629
|
-
) => aegis128XEncryptDetachedInPlace(data, ad, key, nonce, tagLen, 2);
|
|
630
|
-
|
|
631
|
-
/** AEGIS-128X2 in-place decryption - detached mode (degree=2). */
|
|
632
|
-
export const aegis128X2DecryptDetachedInPlace = (
|
|
633
|
-
data: Uint8Array,
|
|
634
|
-
tag: Uint8Array,
|
|
635
|
-
ad: Uint8Array,
|
|
636
|
-
key: Uint8Array,
|
|
637
|
-
nonce: Uint8Array,
|
|
638
|
-
) => aegis128XDecryptDetachedInPlace(data, tag, ad, key, nonce, 2);
|
|
639
|
-
|
|
640
|
-
/** AEGIS-128X4 in-place encryption - detached mode (degree=4). */
|
|
641
|
-
export const aegis128X4EncryptDetachedInPlace = (
|
|
642
|
-
data: Uint8Array,
|
|
643
|
-
ad: Uint8Array,
|
|
644
|
-
key: Uint8Array,
|
|
645
|
-
nonce: Uint8Array,
|
|
646
|
-
tagLen: 16 | 32 = 16,
|
|
647
|
-
) => aegis128XEncryptDetachedInPlace(data, ad, key, nonce, tagLen, 4);
|
|
648
|
-
|
|
649
|
-
/** AEGIS-128X4 in-place decryption - detached mode (degree=4). */
|
|
650
|
-
export const aegis128X4DecryptDetachedInPlace = (
|
|
651
|
-
data: Uint8Array,
|
|
652
|
-
tag: Uint8Array,
|
|
653
|
-
ad: Uint8Array,
|
|
654
|
-
key: Uint8Array,
|
|
655
|
-
nonce: Uint8Array,
|
|
656
|
-
) => aegis128XDecryptDetachedInPlace(data, tag, ad, key, nonce, 4);
|
|
657
|
-
|
|
658
|
-
/** Nonce size for AEGIS-128X in bytes. */
|
|
659
|
-
export const AEGIS_128X_NONCE_SIZE = 16;
|
|
660
|
-
|
|
661
|
-
/** Key size for AEGIS-128X in bytes. */
|
|
662
|
-
export const AEGIS_128X_KEY_SIZE = 16;
|
|
663
|
-
|
|
664
|
-
/**
|
|
665
|
-
* Encrypts a message using AEGIS-128X.
|
|
666
|
-
* Returns a single buffer containing nonce || ciphertext || tag.
|
|
667
|
-
* @param msg - Plaintext message
|
|
668
|
-
* @param ad - Associated data (authenticated but not encrypted)
|
|
669
|
-
* @param key - 16-byte encryption key
|
|
670
|
-
* @param nonce - 16-byte nonce (optional, generates random nonce if not provided)
|
|
671
|
-
* @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
|
|
672
|
-
* @param degree - Parallelism degree (default: 2)
|
|
673
|
-
* @returns Concatenated nonce || ciphertext || tag
|
|
674
|
-
*/
|
|
675
|
-
export function aegis128XEncrypt(
|
|
676
|
-
msg: Uint8Array,
|
|
677
|
-
ad: Uint8Array,
|
|
678
|
-
key: Uint8Array,
|
|
679
|
-
nonce: Uint8Array | null = null,
|
|
680
|
-
tagLen: 16 | 32 = 16,
|
|
681
|
-
degree: number = 2,
|
|
682
|
-
): Uint8Array {
|
|
683
|
-
const actualNonce = nonce ?? randomBytes(AEGIS_128X_NONCE_SIZE);
|
|
684
|
-
const state = new Aegis128XState(degree);
|
|
685
|
-
const rateBytes = (256 * degree) / 8;
|
|
686
|
-
|
|
687
|
-
state.init(key, actualNonce);
|
|
688
|
-
|
|
689
|
-
const adPadded = zeroPad(ad, rateBytes);
|
|
690
|
-
for (let i = 0; i + rateBytes <= adPadded.length; i += rateBytes) {
|
|
691
|
-
state.absorb(adPadded.subarray(i, i + rateBytes));
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
const nonceSize = AEGIS_128X_NONCE_SIZE;
|
|
695
|
-
const result = new Uint8Array(nonceSize + msg.length + tagLen);
|
|
696
|
-
result.set(actualNonce, 0);
|
|
697
|
-
|
|
698
|
-
const fullBlocks = Math.floor(msg.length / rateBytes) * rateBytes;
|
|
699
|
-
for (let i = 0; i < fullBlocks; i += rateBytes) {
|
|
700
|
-
state.encTo(
|
|
701
|
-
msg.subarray(i, i + rateBytes),
|
|
702
|
-
result.subarray(nonceSize + i, nonceSize + i + rateBytes),
|
|
703
|
-
);
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
if (msg.length > fullBlocks) {
|
|
707
|
-
const lastBlock = zeroPad(msg.subarray(fullBlocks), rateBytes);
|
|
708
|
-
const encBlock = state.enc(lastBlock);
|
|
709
|
-
result.set(
|
|
710
|
-
encBlock.subarray(0, msg.length - fullBlocks),
|
|
711
|
-
nonceSize + fullBlocks,
|
|
712
|
-
);
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
const tag = state.finalize(
|
|
716
|
-
BigInt(ad.length * 8),
|
|
717
|
-
BigInt(msg.length * 8),
|
|
718
|
-
tagLen,
|
|
719
|
-
);
|
|
720
|
-
result.set(tag, nonceSize + msg.length);
|
|
721
|
-
|
|
722
|
-
return result;
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
/**
|
|
726
|
-
* Decrypts a message using AEGIS-128X.
|
|
727
|
-
* Expects input as nonce || ciphertext || tag.
|
|
728
|
-
* @param sealed - Concatenated nonce || ciphertext || tag
|
|
729
|
-
* @param ad - Associated data (must match what was used during encryption)
|
|
730
|
-
* @param key - 16-byte encryption key
|
|
731
|
-
* @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
|
|
732
|
-
* @param degree - Parallelism degree (default: 2)
|
|
733
|
-
* @returns Decrypted plaintext, or null if authentication fails
|
|
734
|
-
*/
|
|
735
|
-
export function aegis128XDecrypt(
|
|
736
|
-
sealed: Uint8Array,
|
|
737
|
-
ad: Uint8Array,
|
|
738
|
-
key: Uint8Array,
|
|
739
|
-
tagLen: 16 | 32 = 16,
|
|
740
|
-
degree: number = 2,
|
|
741
|
-
): Uint8Array | null {
|
|
742
|
-
const nonceSize = AEGIS_128X_NONCE_SIZE;
|
|
743
|
-
if (sealed.length < nonceSize + tagLen) {
|
|
744
|
-
return null;
|
|
745
|
-
}
|
|
746
|
-
const nonce = sealed.subarray(0, nonceSize);
|
|
747
|
-
const ct = sealed.subarray(nonceSize, sealed.length - tagLen);
|
|
748
|
-
const tag = sealed.subarray(sealed.length - tagLen);
|
|
749
|
-
return aegis128XDecryptDetached(ct, tag, ad, key, nonce, degree);
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
/** AEGIS-128X2 encryption - detached mode (degree=2). */
|
|
753
|
-
export const aegis128X2EncryptDetached = (
|
|
754
|
-
msg: Uint8Array,
|
|
755
|
-
ad: Uint8Array,
|
|
756
|
-
key: Uint8Array,
|
|
757
|
-
nonce: Uint8Array,
|
|
758
|
-
tagLen: 16 | 32 = 16,
|
|
759
|
-
) => aegis128XEncryptDetached(msg, ad, key, nonce, tagLen, 2);
|
|
760
|
-
|
|
761
|
-
/** AEGIS-128X2 decryption - detached mode (degree=2). */
|
|
762
|
-
export const aegis128X2DecryptDetached = (
|
|
763
|
-
ct: Uint8Array,
|
|
764
|
-
tag: Uint8Array,
|
|
765
|
-
ad: Uint8Array,
|
|
766
|
-
key: Uint8Array,
|
|
767
|
-
nonce: Uint8Array,
|
|
768
|
-
) => aegis128XDecryptDetached(ct, tag, ad, key, nonce, 2);
|
|
769
|
-
|
|
770
|
-
/** AEGIS-128X4 encryption - detached mode (degree=4). */
|
|
771
|
-
export const aegis128X4EncryptDetached = (
|
|
772
|
-
msg: Uint8Array,
|
|
773
|
-
ad: Uint8Array,
|
|
774
|
-
key: Uint8Array,
|
|
775
|
-
nonce: Uint8Array,
|
|
776
|
-
tagLen: 16 | 32 = 16,
|
|
777
|
-
) => aegis128XEncryptDetached(msg, ad, key, nonce, tagLen, 4);
|
|
778
|
-
|
|
779
|
-
/** AEGIS-128X4 decryption - detached mode (degree=4). */
|
|
780
|
-
export const aegis128X4DecryptDetached = (
|
|
781
|
-
ct: Uint8Array,
|
|
782
|
-
tag: Uint8Array,
|
|
783
|
-
ad: Uint8Array,
|
|
784
|
-
key: Uint8Array,
|
|
785
|
-
nonce: Uint8Array,
|
|
786
|
-
) => aegis128XDecryptDetached(ct, tag, ad, key, nonce, 4);
|
|
787
|
-
|
|
788
|
-
/** AEGIS-128X2 encryption (degree=2). */
|
|
789
|
-
export const aegis128X2Encrypt = (
|
|
790
|
-
msg: Uint8Array,
|
|
791
|
-
ad: Uint8Array,
|
|
792
|
-
key: Uint8Array,
|
|
793
|
-
nonce: Uint8Array | null = null,
|
|
794
|
-
tagLen: 16 | 32 = 16,
|
|
795
|
-
) => aegis128XEncrypt(msg, ad, key, nonce, tagLen, 2);
|
|
796
|
-
|
|
797
|
-
/** AEGIS-128X2 decryption (degree=2). */
|
|
798
|
-
export const aegis128X2Decrypt = (
|
|
799
|
-
sealed: Uint8Array,
|
|
800
|
-
ad: Uint8Array,
|
|
801
|
-
key: Uint8Array,
|
|
802
|
-
tagLen: 16 | 32 = 16,
|
|
803
|
-
) => aegis128XDecrypt(sealed, ad, key, tagLen, 2);
|
|
804
|
-
|
|
805
|
-
/** AEGIS-128X4 encryption (degree=4). */
|
|
806
|
-
export const aegis128X4Encrypt = (
|
|
807
|
-
msg: Uint8Array,
|
|
808
|
-
ad: Uint8Array,
|
|
809
|
-
key: Uint8Array,
|
|
810
|
-
nonce: Uint8Array | null = null,
|
|
811
|
-
tagLen: 16 | 32 = 16,
|
|
812
|
-
) => aegis128XEncrypt(msg, ad, key, nonce, tagLen, 4);
|
|
813
|
-
|
|
814
|
-
/** AEGIS-128X4 decryption (degree=4). */
|
|
815
|
-
export const aegis128X4Decrypt = (
|
|
816
|
-
sealed: Uint8Array,
|
|
817
|
-
ad: Uint8Array,
|
|
818
|
-
key: Uint8Array,
|
|
819
|
-
tagLen: 16 | 32 = 16,
|
|
820
|
-
) => aegis128XDecrypt(sealed, ad, key, tagLen, 4);
|
|
821
|
-
|
|
822
|
-
/**
|
|
823
|
-
* Computes a MAC (Message Authentication Code) using AEGIS-128X.
|
|
824
|
-
* @param data - Data to authenticate
|
|
825
|
-
* @param key - 16-byte key
|
|
826
|
-
* @param nonce - 16-byte nonce (optional, uses zero nonce if null)
|
|
827
|
-
* @param tagLen - Tag length: 16 or 32 bytes (default: 16)
|
|
828
|
-
* @param degree - Parallelism degree (default: 2)
|
|
829
|
-
* @returns Authentication tag
|
|
830
|
-
*/
|
|
831
|
-
export function aegis128XMac(
|
|
832
|
-
data: Uint8Array,
|
|
833
|
-
key: Uint8Array,
|
|
834
|
-
nonce: Uint8Array | null = null,
|
|
835
|
-
tagLen: 16 | 32 = 16,
|
|
836
|
-
degree: number = 2,
|
|
837
|
-
): Uint8Array {
|
|
838
|
-
const state = new Aegis128XState(degree);
|
|
839
|
-
const rateBytes = (256 * degree) / 8;
|
|
840
|
-
|
|
841
|
-
state.init(key, nonce ?? new Uint8Array(16));
|
|
842
|
-
|
|
843
|
-
const dataPadded = zeroPad(data, rateBytes);
|
|
844
|
-
for (let i = 0; i + rateBytes <= dataPadded.length; i += rateBytes) {
|
|
845
|
-
state.absorb(dataPadded.subarray(i, i + rateBytes));
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
return state.finalizeMac(BigInt(data.length * 8), tagLen);
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
/**
|
|
852
|
-
* Verifies a MAC computed using AEGIS-128X.
|
|
853
|
-
* @param data - Data to verify
|
|
854
|
-
* @param tag - Expected authentication tag (16 or 32 bytes)
|
|
855
|
-
* @param key - 16-byte key
|
|
856
|
-
* @param nonce - 16-byte nonce (optional, uses zero nonce if null)
|
|
857
|
-
* @param degree - Parallelism degree (default: 2)
|
|
858
|
-
* @returns True if the tag is valid, false otherwise
|
|
859
|
-
*/
|
|
860
|
-
export function aegis128XMacVerify(
|
|
861
|
-
data: Uint8Array,
|
|
862
|
-
tag: Uint8Array,
|
|
863
|
-
key: Uint8Array,
|
|
864
|
-
nonce: Uint8Array | null = null,
|
|
865
|
-
degree: number = 2,
|
|
866
|
-
): boolean {
|
|
867
|
-
const tagLen = tag.length as 16 | 32;
|
|
868
|
-
const expectedTag = aegis128XMac(data, key, nonce, tagLen, degree);
|
|
869
|
-
return constantTimeEqual(tag, expectedTag);
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
/** AEGIS-128X2 MAC computation (degree=2). */
|
|
873
|
-
export const aegis128X2Mac = (
|
|
874
|
-
data: Uint8Array,
|
|
875
|
-
key: Uint8Array,
|
|
876
|
-
nonce: Uint8Array | null = null,
|
|
877
|
-
tagLen: 16 | 32 = 16,
|
|
878
|
-
) => aegis128XMac(data, key, nonce, tagLen, 2);
|
|
879
|
-
|
|
880
|
-
/** AEGIS-128X2 MAC verification (degree=2). */
|
|
881
|
-
export const aegis128X2MacVerify = (
|
|
882
|
-
data: Uint8Array,
|
|
883
|
-
tag: Uint8Array,
|
|
884
|
-
key: Uint8Array,
|
|
885
|
-
nonce: Uint8Array | null = null,
|
|
886
|
-
) => aegis128XMacVerify(data, tag, key, nonce, 2);
|
|
887
|
-
|
|
888
|
-
/** AEGIS-128X4 MAC computation (degree=4). */
|
|
889
|
-
export const aegis128X4Mac = (
|
|
890
|
-
data: Uint8Array,
|
|
891
|
-
key: Uint8Array,
|
|
892
|
-
nonce: Uint8Array | null = null,
|
|
893
|
-
tagLen: 16 | 32 = 16,
|
|
894
|
-
) => aegis128XMac(data, key, nonce, tagLen, 4);
|
|
895
|
-
|
|
896
|
-
/** AEGIS-128X4 MAC verification (degree=4). */
|
|
897
|
-
export const aegis128X4MacVerify = (
|
|
898
|
-
data: Uint8Array,
|
|
899
|
-
tag: Uint8Array,
|
|
900
|
-
key: Uint8Array,
|
|
901
|
-
nonce: Uint8Array | null = null,
|
|
902
|
-
) => aegis128XMacVerify(data, tag, key, nonce, 4);
|
|
903
|
-
|
|
904
|
-
/**
|
|
905
|
-
* Generates a random 16-byte key for AEGIS-128X.
|
|
906
|
-
* @returns 16-byte encryption key
|
|
907
|
-
* @throws Error if no cryptographic random source is available
|
|
908
|
-
*/
|
|
909
|
-
export function aegis128XCreateKey(): Uint8Array {
|
|
910
|
-
return randomBytes(AEGIS_128X_KEY_SIZE);
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
/**
|
|
914
|
-
* Generates a random 16-byte nonce for AEGIS-128X.
|
|
915
|
-
* @returns 16-byte nonce
|
|
916
|
-
* @throws Error if no cryptographic random source is available
|
|
917
|
-
*/
|
|
918
|
-
export function aegis128XCreateNonce(): Uint8Array {
|
|
919
|
-
return randomBytes(AEGIS_128X_NONCE_SIZE);
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
/** AEGIS-128X2 key generation (degree=2). */
|
|
923
|
-
export const aegis128X2CreateKey = aegis128XCreateKey;
|
|
924
|
-
|
|
925
|
-
/** AEGIS-128X2 nonce generation (degree=2). */
|
|
926
|
-
export const aegis128X2CreateNonce = aegis128XCreateNonce;
|
|
927
|
-
|
|
928
|
-
/** AEGIS-128X4 key generation (degree=4). */
|
|
929
|
-
export const aegis128X4CreateKey = aegis128XCreateKey;
|
|
930
|
-
|
|
931
|
-
/** AEGIS-128X4 nonce generation (degree=4). */
|
|
932
|
-
export const aegis128X4CreateNonce = aegis128XCreateNonce;
|