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.
- package/README.md +29 -22
- 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 +46 -23
- package/dist/aes-bs.js +2273 -331
- 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 +6 -6
- package/dist/aegis128l-bs.d.ts +0 -194
- package/dist/aegis128l-bs.d.ts.map +0 -1
- package/dist/aegis128l-bs.js +0 -549
- 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 -183
- package/dist/aegis256-bs.d.ts.map +0 -1
- package/dist/aegis256-bs.js +0 -477
- 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 -709
- package/src/aegis128l.ts +0 -653
- package/src/aegis128x.ts +0 -932
- package/src/aegis256-bs.ts +0 -625
- package/src/aegis256.ts +0 -597
- package/src/aegis256x.ts +0 -893
- package/src/aes-bs.ts +0 -459
- 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/dist/aegis256.js
CHANGED
|
@@ -1,32 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* AEGIS-256 implementation.
|
|
3
|
+
* Built on the constant-time bitsliced AES core, which processes the state
|
|
4
|
+
* blocks simultaneously without lookup tables.
|
|
5
|
+
*/
|
|
6
|
+
import { aegisRound256, blockFromBytes, blocksPut, blockToBytes, blockXor, createAesBlock, createAesBlocks, keystream256, pack, packConstantInput256, unpack, wordIdx, } from "./aes-bs.js";
|
|
2
7
|
import { randomBytes } from "./random.js";
|
|
8
|
+
import { constantTimeEqual, zeroPad } from "./utils.js";
|
|
9
|
+
const RATE = 16;
|
|
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-256 cipher state.
|
|
5
|
-
* Uses 6 AES blocks
|
|
18
|
+
* Uses 6 AES blocks stored in packed bitsliced form throughout the lifetime
|
|
19
|
+
* of the state.
|
|
6
20
|
*/
|
|
7
21
|
export class Aegis256State {
|
|
8
22
|
constructor() {
|
|
9
|
-
this.
|
|
10
|
-
this.
|
|
11
|
-
this.
|
|
12
|
-
this.
|
|
13
|
-
this.s4 = new Uint8Array(16);
|
|
14
|
-
this.s5 = new Uint8Array(16);
|
|
15
|
-
this.tmp = new Uint8Array(16);
|
|
16
|
-
this.z = new Uint8Array(16);
|
|
17
|
-
this.newS = Array.from({ length: 6 }, () => new Uint8Array(16));
|
|
18
|
-
this.tBuf = new Uint8Array(16);
|
|
23
|
+
this.st = createAesBlocks();
|
|
24
|
+
this.constantInput = createAesBlocks();
|
|
25
|
+
this.tmp = createAesBlock();
|
|
26
|
+
this.z = createAesBlock();
|
|
19
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Returns the 6 state blocks as byte arrays (for testing).
|
|
30
|
+
*/
|
|
20
31
|
get s() {
|
|
21
|
-
|
|
32
|
+
const unpacked = createAesBlocks();
|
|
33
|
+
unpacked.set(this.st);
|
|
34
|
+
unpack(unpacked);
|
|
35
|
+
const blocks = [];
|
|
36
|
+
const w = createAesBlock();
|
|
37
|
+
for (let i = 0; i < 6; i++) {
|
|
38
|
+
for (let j = 0; j < 4; j++)
|
|
39
|
+
w[j] = unpacked[wordIdx(i, j)];
|
|
40
|
+
const bytes = new Uint8Array(16);
|
|
41
|
+
blockToBytes(bytes, w);
|
|
42
|
+
blocks.push(bytes);
|
|
43
|
+
}
|
|
44
|
+
return blocks;
|
|
22
45
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this.
|
|
28
|
-
|
|
29
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Sets the 6 state blocks from byte arrays (for testing).
|
|
48
|
+
*/
|
|
49
|
+
set s(blocks) {
|
|
50
|
+
this.st.fill(0);
|
|
51
|
+
const w = createAesBlock();
|
|
52
|
+
for (let i = 0; i < 6; i++) {
|
|
53
|
+
blockFromBytes(w, blocks[i]);
|
|
54
|
+
blocksPut(this.st, w, i);
|
|
55
|
+
}
|
|
56
|
+
pack(this.st);
|
|
30
57
|
}
|
|
31
58
|
/**
|
|
32
59
|
* Initializes the state with a key and nonce.
|
|
@@ -34,184 +61,179 @@ export class Aegis256State {
|
|
|
34
61
|
* @param nonce - 32-byte nonce (must be unique per message)
|
|
35
62
|
*/
|
|
36
63
|
init(key, nonce) {
|
|
37
|
-
const k0 =
|
|
38
|
-
const k1 =
|
|
39
|
-
const n0 =
|
|
40
|
-
const n1 =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
64
|
+
const k0 = createAesBlock();
|
|
65
|
+
const k1 = createAesBlock();
|
|
66
|
+
const n0 = createAesBlock();
|
|
67
|
+
const n1 = createAesBlock();
|
|
68
|
+
const k0n0 = createAesBlock();
|
|
69
|
+
const k1n1 = createAesBlock();
|
|
70
|
+
const k0c0 = createAesBlock();
|
|
71
|
+
const k1c1 = createAesBlock();
|
|
72
|
+
blockFromBytes(k0, key);
|
|
73
|
+
blockFromBytes(k1, key, 16);
|
|
74
|
+
blockFromBytes(n0, nonce);
|
|
75
|
+
blockFromBytes(n1, nonce, 16);
|
|
76
|
+
blockXor(k0n0, k0, n0);
|
|
77
|
+
blockXor(k1n1, k1, n1);
|
|
78
|
+
blockXor(k0c0, k0, C0);
|
|
79
|
+
blockXor(k1c1, k1, C1);
|
|
80
|
+
this.st.fill(0);
|
|
81
|
+
blocksPut(this.st, k0n0, 0);
|
|
82
|
+
blocksPut(this.st, k1n1, 1);
|
|
83
|
+
blocksPut(this.st, C1, 2);
|
|
84
|
+
blocksPut(this.st, C0, 3);
|
|
85
|
+
blocksPut(this.st, k0c0, 4);
|
|
86
|
+
blocksPut(this.st, k1c1, 5);
|
|
87
|
+
const ciK0 = createAesBlocks();
|
|
88
|
+
const ciK1 = createAesBlocks();
|
|
89
|
+
const ciK0N0 = createAesBlocks();
|
|
90
|
+
const ciK1N1 = createAesBlocks();
|
|
91
|
+
packConstantInput256(ciK0, k0);
|
|
92
|
+
packConstantInput256(ciK1, k1);
|
|
93
|
+
packConstantInput256(ciK0N0, k0n0);
|
|
94
|
+
packConstantInput256(ciK1N1, k1n1);
|
|
95
|
+
pack(this.st);
|
|
51
96
|
for (let i = 0; i < 4; i++) {
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
97
|
+
aegisRound256(this.st, ciK0);
|
|
98
|
+
aegisRound256(this.st, ciK1);
|
|
99
|
+
aegisRound256(this.st, ciK0N0);
|
|
100
|
+
aegisRound256(this.st, ciK1N1);
|
|
56
101
|
}
|
|
57
102
|
}
|
|
58
103
|
/**
|
|
59
104
|
* Updates the state with a 16-byte message block.
|
|
60
|
-
* @param m -
|
|
105
|
+
* @param m - 16-byte message block
|
|
61
106
|
*/
|
|
62
107
|
update(m) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
aesRoundTo(this.s0, this.s1, newS[1]);
|
|
67
|
-
aesRoundTo(this.s1, this.s2, newS[2]);
|
|
68
|
-
aesRoundTo(this.s2, this.s3, newS[3]);
|
|
69
|
-
aesRoundTo(this.s3, this.s4, newS[4]);
|
|
70
|
-
aesRoundTo(this.s4, this.s5, newS[5]);
|
|
71
|
-
this.s0.set(newS[0]);
|
|
72
|
-
this.s1.set(newS[1]);
|
|
73
|
-
this.s2.set(newS[2]);
|
|
74
|
-
this.s3.set(newS[3]);
|
|
75
|
-
this.s4.set(newS[4]);
|
|
76
|
-
this.s5.set(newS[5]);
|
|
108
|
+
blockFromBytes(this.tmp, m);
|
|
109
|
+
packConstantInput256(this.constantInput, this.tmp);
|
|
110
|
+
aegisRound256(this.st, this.constantInput);
|
|
77
111
|
}
|
|
78
112
|
/**
|
|
79
113
|
* Absorbs a 16-byte associated data block into the state.
|
|
80
|
-
* @param ai - 16-byte associated data block
|
|
114
|
+
* @param ai - Buffer holding the 16-byte associated data block
|
|
115
|
+
* @param off - Offset of the block within the buffer
|
|
81
116
|
*/
|
|
82
|
-
absorb(ai) {
|
|
83
|
-
this.
|
|
117
|
+
absorb(ai, off = 0) {
|
|
118
|
+
const msg = this.tmp;
|
|
119
|
+
blockFromBytes(msg, ai, off);
|
|
120
|
+
packConstantInput256(this.constantInput, msg);
|
|
121
|
+
aegisRound256(this.st, this.constantInput);
|
|
84
122
|
}
|
|
85
123
|
/**
|
|
86
|
-
* Encrypts a 16-byte plaintext block and writes to output.
|
|
87
|
-
* @param xi - 16-byte plaintext block
|
|
88
|
-
* @param out - 16-byte
|
|
124
|
+
* Encrypts a 16-byte plaintext block and writes to output buffer.
|
|
125
|
+
* @param xi - Buffer holding the 16-byte plaintext block
|
|
126
|
+
* @param out - Output buffer receiving the 16-byte ciphertext block
|
|
127
|
+
* @param inOff - Offset of the plaintext block within xi
|
|
128
|
+
* @param outOff - Offset of the ciphertext block within out
|
|
89
129
|
*/
|
|
90
|
-
encTo(xi, out) {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
z[i] ^= tmp[i];
|
|
99
|
-
this.update(xi);
|
|
100
|
-
for (let i = 0; i < 16; i++)
|
|
101
|
-
out[i] = xi[i] ^ z[i];
|
|
130
|
+
encTo(xi, out, inOff = 0, outOff = 0) {
|
|
131
|
+
const t = this.tmp;
|
|
132
|
+
keystream256(this.st, this.z);
|
|
133
|
+
blockFromBytes(t, xi, inOff);
|
|
134
|
+
packConstantInput256(this.constantInput, t);
|
|
135
|
+
aegisRound256(this.st, this.constantInput);
|
|
136
|
+
blockXor(t, t, this.z);
|
|
137
|
+
blockToBytes(out, t, outOff);
|
|
102
138
|
}
|
|
103
|
-
/**
|
|
104
|
-
* Encrypts a 16-byte plaintext block.
|
|
105
|
-
* @param xi - 16-byte plaintext block
|
|
106
|
-
* @returns 16-byte ciphertext block
|
|
107
|
-
*/
|
|
108
139
|
enc(xi) {
|
|
109
140
|
const out = new Uint8Array(16);
|
|
110
141
|
this.encTo(xi, out);
|
|
111
142
|
return out;
|
|
112
143
|
}
|
|
113
144
|
/**
|
|
114
|
-
* Decrypts a 16-byte ciphertext block and writes to output.
|
|
115
|
-
* @param ci - 16-byte ciphertext block
|
|
116
|
-
* @param out - 16-byte
|
|
145
|
+
* Decrypts a 16-byte ciphertext block and writes to output buffer.
|
|
146
|
+
* @param ci - Buffer holding the 16-byte ciphertext block
|
|
147
|
+
* @param out - Output buffer receiving the 16-byte plaintext block
|
|
148
|
+
* @param inOff - Offset of the ciphertext block within ci
|
|
149
|
+
* @param outOff - Offset of the plaintext block within out
|
|
117
150
|
*/
|
|
118
|
-
decTo(ci, out) {
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
z[i] ^= tmp[i];
|
|
127
|
-
for (let i = 0; i < 16; i++)
|
|
128
|
-
out[i] = ci[i] ^ z[i];
|
|
129
|
-
this.update(out);
|
|
151
|
+
decTo(ci, out, inOff = 0, outOff = 0) {
|
|
152
|
+
const msg = this.tmp;
|
|
153
|
+
blockFromBytes(msg, ci, inOff);
|
|
154
|
+
keystream256(this.st, this.z);
|
|
155
|
+
blockXor(msg, msg, this.z);
|
|
156
|
+
packConstantInput256(this.constantInput, msg);
|
|
157
|
+
aegisRound256(this.st, this.constantInput);
|
|
158
|
+
blockToBytes(out, msg, outOff);
|
|
130
159
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Decrypts a 16-byte ciphertext block.
|
|
133
|
-
* @param ci - 16-byte ciphertext block
|
|
134
|
-
* @returns 16-byte plaintext block
|
|
135
|
-
*/
|
|
136
160
|
dec(ci) {
|
|
137
161
|
const out = new Uint8Array(16);
|
|
138
162
|
this.decTo(ci, out);
|
|
139
163
|
return out;
|
|
140
164
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Encrypts a 16-byte plaintext block in-place.
|
|
143
|
-
* @param block - 16-byte buffer (plaintext in, ciphertext out)
|
|
144
|
-
*/
|
|
145
165
|
encInPlace(block) {
|
|
146
166
|
this.encTo(block, block);
|
|
147
167
|
}
|
|
148
|
-
/**
|
|
149
|
-
* Decrypts a 16-byte ciphertext block in-place.
|
|
150
|
-
* @param block - 16-byte buffer (ciphertext in, plaintext out)
|
|
151
|
-
*/
|
|
152
168
|
decInPlace(block) {
|
|
153
169
|
this.decTo(block, block);
|
|
154
170
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Decrypts a partial (final) ciphertext block smaller than 16 bytes.
|
|
157
|
-
* @param cn - Partial ciphertext block (1-15 bytes)
|
|
158
|
-
* @returns Decrypted plaintext of the same length
|
|
159
|
-
*/
|
|
160
171
|
decPartial(cn) {
|
|
161
|
-
const
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const xn = new Uint8Array(out.subarray(0, cn.length));
|
|
174
|
-
const v = zeroPad(xn, 16);
|
|
175
|
-
this.update(v);
|
|
172
|
+
const msg = this.tmp;
|
|
173
|
+
const padded = zeroPad(cn, RATE);
|
|
174
|
+
blockFromBytes(msg, padded);
|
|
175
|
+
keystream256(this.st, this.z);
|
|
176
|
+
blockXor(msg, msg, this.z);
|
|
177
|
+
const pad = new Uint8Array(RATE);
|
|
178
|
+
blockToBytes(pad, msg);
|
|
179
|
+
const xn = new Uint8Array(pad.subarray(0, cn.length));
|
|
180
|
+
pad.fill(0, cn.length);
|
|
181
|
+
blockFromBytes(msg, pad);
|
|
182
|
+
packConstantInput256(this.constantInput, msg);
|
|
183
|
+
aegisRound256(this.st, this.constantInput);
|
|
176
184
|
return xn;
|
|
177
185
|
}
|
|
178
186
|
/**
|
|
179
187
|
* Finalizes encryption/decryption and produces an authentication tag.
|
|
180
|
-
* @param adLenBits - Associated data length in bits
|
|
181
|
-
* @param msgLenBits - Message length in bits
|
|
182
|
-
* @param tagLen - Tag length (16 or 32 bytes)
|
|
183
|
-
* @returns Authentication tag
|
|
184
188
|
*/
|
|
185
|
-
finalize(
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
finalize(adLen, msgLen, tagLen = 16) {
|
|
190
|
+
const st = this.st;
|
|
191
|
+
const tmp = this.tmp;
|
|
192
|
+
tmp[0] = (adLen * 8) & 0xffffffff;
|
|
193
|
+
tmp[1] = Math.floor((adLen * 8) / 0x100000000);
|
|
194
|
+
tmp[2] = (msgLen * 8) & 0xffffffff;
|
|
195
|
+
tmp[3] = Math.floor((msgLen * 8) / 0x100000000);
|
|
196
|
+
const unpacked = createAesBlocks();
|
|
197
|
+
unpacked.set(st);
|
|
198
|
+
unpack(unpacked);
|
|
199
|
+
tmp[0] = tmp[0] ^ unpacked[wordIdx(3, 0)];
|
|
200
|
+
tmp[1] = tmp[1] ^ unpacked[wordIdx(3, 1)];
|
|
201
|
+
tmp[2] = tmp[2] ^ unpacked[wordIdx(3, 2)];
|
|
202
|
+
tmp[3] = tmp[3] ^ unpacked[wordIdx(3, 3)];
|
|
203
|
+
packConstantInput256(this.constantInput, tmp);
|
|
191
204
|
for (let i = 0; i < 7; i++) {
|
|
192
|
-
this.
|
|
205
|
+
aegisRound256(st, this.constantInput);
|
|
193
206
|
}
|
|
207
|
+
unpack(st);
|
|
194
208
|
if (tagLen === 16) {
|
|
195
209
|
const tag = new Uint8Array(16);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
210
|
+
const tagBlock = createAesBlock();
|
|
211
|
+
for (let i = 0; i < 4; i++) {
|
|
212
|
+
tagBlock[i] =
|
|
213
|
+
st[wordIdx(0, i)] ^
|
|
214
|
+
st[wordIdx(1, i)] ^
|
|
215
|
+
st[wordIdx(2, i)] ^
|
|
216
|
+
st[wordIdx(3, i)] ^
|
|
217
|
+
st[wordIdx(4, i)] ^
|
|
218
|
+
st[wordIdx(5, i)];
|
|
204
219
|
}
|
|
220
|
+
blockToBytes(tag, tagBlock);
|
|
205
221
|
return tag;
|
|
206
222
|
}
|
|
207
223
|
else {
|
|
208
224
|
const tag = new Uint8Array(32);
|
|
209
|
-
|
|
210
|
-
|
|
225
|
+
const tagBlock0 = createAesBlock();
|
|
226
|
+
const tagBlock1 = createAesBlock();
|
|
227
|
+
for (let i = 0; i < 4; i++) {
|
|
228
|
+
tagBlock0[i] =
|
|
229
|
+
st[wordIdx(0, i)] ^ st[wordIdx(1, i)] ^ st[wordIdx(2, i)];
|
|
211
230
|
}
|
|
212
|
-
for (let i = 0; i <
|
|
213
|
-
|
|
231
|
+
for (let i = 0; i < 4; i++) {
|
|
232
|
+
tagBlock1[i] =
|
|
233
|
+
st[wordIdx(3, i)] ^ st[wordIdx(4, i)] ^ st[wordIdx(5, i)];
|
|
214
234
|
}
|
|
235
|
+
blockToBytes(tag, tagBlock0);
|
|
236
|
+
blockToBytes(tag, tagBlock1, 16);
|
|
215
237
|
return tag;
|
|
216
238
|
}
|
|
217
239
|
}
|
|
@@ -228,17 +250,21 @@ export class Aegis256State {
|
|
|
228
250
|
export function aegis256EncryptDetached(msg, ad, key, nonce, tagLen = 16) {
|
|
229
251
|
const state = new Aegis256State();
|
|
230
252
|
state.init(key, nonce);
|
|
231
|
-
const adPadded = zeroPad(ad,
|
|
232
|
-
for (let i = 0; i +
|
|
233
|
-
state.absorb(adPadded
|
|
253
|
+
const adPadded = zeroPad(ad, RATE);
|
|
254
|
+
for (let i = 0; i + RATE <= adPadded.length; i += RATE) {
|
|
255
|
+
state.absorb(adPadded, i);
|
|
234
256
|
}
|
|
235
|
-
const
|
|
236
|
-
const
|
|
237
|
-
for (let i = 0; i
|
|
238
|
-
state.encTo(
|
|
257
|
+
const ciphertext = new Uint8Array(msg.length);
|
|
258
|
+
const fullBlocks = Math.floor(msg.length / RATE) * RATE;
|
|
259
|
+
for (let i = 0; i < fullBlocks; i += RATE) {
|
|
260
|
+
state.encTo(msg, ciphertext, i, i);
|
|
261
|
+
}
|
|
262
|
+
if (msg.length > fullBlocks) {
|
|
263
|
+
const lastBlock = zeroPad(msg.subarray(fullBlocks), RATE);
|
|
264
|
+
const encBlock = state.enc(lastBlock);
|
|
265
|
+
ciphertext.set(encBlock.subarray(0, msg.length - fullBlocks), fullBlocks);
|
|
239
266
|
}
|
|
240
|
-
const tag = state.finalize(
|
|
241
|
-
const ciphertext = new Uint8Array(ct.subarray(0, msg.length));
|
|
267
|
+
const tag = state.finalize(ad.length, msg.length, tagLen);
|
|
242
268
|
return { ciphertext, tag };
|
|
243
269
|
}
|
|
244
270
|
/**
|
|
@@ -254,20 +280,19 @@ export function aegis256DecryptDetached(ct, tag, ad, key, nonce) {
|
|
|
254
280
|
const tagLen = tag.length;
|
|
255
281
|
const state = new Aegis256State();
|
|
256
282
|
state.init(key, nonce);
|
|
257
|
-
const adPadded = zeroPad(ad,
|
|
258
|
-
for (let i = 0; i +
|
|
259
|
-
state.absorb(adPadded
|
|
283
|
+
const adPadded = zeroPad(ad, RATE);
|
|
284
|
+
for (let i = 0; i + RATE <= adPadded.length; i += RATE) {
|
|
285
|
+
state.absorb(adPadded, i);
|
|
260
286
|
}
|
|
261
|
-
const
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
state.decTo(ct.subarray(i, i + 16), msg.subarray(i, i + 16));
|
|
287
|
+
const msg = new Uint8Array(ct.length);
|
|
288
|
+
const fullBlocks = Math.floor(ct.length / RATE) * RATE;
|
|
289
|
+
for (let i = 0; i < fullBlocks; i += RATE) {
|
|
290
|
+
state.decTo(ct, msg, i, i);
|
|
266
291
|
}
|
|
267
|
-
if (
|
|
268
|
-
msg.set(state.decPartial(
|
|
292
|
+
if (ct.length > fullBlocks) {
|
|
293
|
+
msg.set(state.decPartial(ct.subarray(fullBlocks)), fullBlocks);
|
|
269
294
|
}
|
|
270
|
-
const expectedTag = state.finalize(
|
|
295
|
+
const expectedTag = state.finalize(ad.length, msg.length, tagLen);
|
|
271
296
|
if (!constantTimeEqual(tag, expectedTag)) {
|
|
272
297
|
msg.fill(0);
|
|
273
298
|
return null;
|
|
@@ -287,22 +312,22 @@ export function aegis256DecryptDetached(ct, tag, ad, key, nonce) {
|
|
|
287
312
|
export function aegis256EncryptDetachedInPlace(data, ad, key, nonce, tagLen = 16) {
|
|
288
313
|
const state = new Aegis256State();
|
|
289
314
|
state.init(key, nonce);
|
|
290
|
-
const adPadded = zeroPad(ad,
|
|
291
|
-
for (let i = 0; i +
|
|
292
|
-
state.absorb(adPadded
|
|
315
|
+
const adPadded = zeroPad(ad, RATE);
|
|
316
|
+
for (let i = 0; i + RATE <= adPadded.length; i += RATE) {
|
|
317
|
+
state.absorb(adPadded, i);
|
|
293
318
|
}
|
|
294
319
|
const msgLen = data.length;
|
|
295
|
-
const fullBlocksLen = Math.floor(msgLen /
|
|
296
|
-
for (let i = 0; i < fullBlocksLen; i +=
|
|
297
|
-
state.
|
|
320
|
+
const fullBlocksLen = Math.floor(msgLen / RATE) * RATE;
|
|
321
|
+
for (let i = 0; i < fullBlocksLen; i += RATE) {
|
|
322
|
+
state.encTo(data, data, i, i);
|
|
298
323
|
}
|
|
299
324
|
if (msgLen > fullBlocksLen) {
|
|
300
325
|
const lastPartial = data.subarray(fullBlocksLen);
|
|
301
|
-
const lastBlock = zeroPad(lastPartial,
|
|
326
|
+
const lastBlock = zeroPad(lastPartial, RATE);
|
|
302
327
|
const encBlock = state.enc(lastBlock);
|
|
303
328
|
lastPartial.set(encBlock.subarray(0, lastPartial.length));
|
|
304
329
|
}
|
|
305
|
-
return state.finalize(
|
|
330
|
+
return state.finalize(ad.length, msgLen, tagLen);
|
|
306
331
|
}
|
|
307
332
|
/**
|
|
308
333
|
* Decrypts a message in-place using AEGIS-256 (detached mode).
|
|
@@ -318,21 +343,21 @@ export function aegis256DecryptDetachedInPlace(data, tag, ad, key, nonce) {
|
|
|
318
343
|
const tagLen = tag.length;
|
|
319
344
|
const state = new Aegis256State();
|
|
320
345
|
state.init(key, nonce);
|
|
321
|
-
const adPadded = zeroPad(ad,
|
|
322
|
-
for (let i = 0; i +
|
|
323
|
-
state.absorb(adPadded
|
|
346
|
+
const adPadded = zeroPad(ad, RATE);
|
|
347
|
+
for (let i = 0; i + RATE <= adPadded.length; i += RATE) {
|
|
348
|
+
state.absorb(adPadded, i);
|
|
324
349
|
}
|
|
325
350
|
const msgLen = data.length;
|
|
326
|
-
const fullBlocksLen = Math.floor(msgLen /
|
|
327
|
-
for (let i = 0; i < fullBlocksLen; i +=
|
|
328
|
-
state.
|
|
351
|
+
const fullBlocksLen = Math.floor(msgLen / RATE) * RATE;
|
|
352
|
+
for (let i = 0; i < fullBlocksLen; i += RATE) {
|
|
353
|
+
state.decTo(data, data, i, i);
|
|
329
354
|
}
|
|
330
355
|
if (msgLen > fullBlocksLen) {
|
|
331
356
|
const lastPartial = data.subarray(fullBlocksLen);
|
|
332
357
|
const decrypted = state.decPartial(lastPartial);
|
|
333
358
|
lastPartial.set(decrypted);
|
|
334
359
|
}
|
|
335
|
-
const expectedTag = state.finalize(
|
|
360
|
+
const expectedTag = state.finalize(ad.length, msgLen, tagLen);
|
|
336
361
|
if (!constantTimeEqual(tag, expectedTag)) {
|
|
337
362
|
data.fill(0);
|
|
338
363
|
return false;
|
|
@@ -355,26 +380,11 @@ export const AEGIS_256_KEY_SIZE = 32;
|
|
|
355
380
|
*/
|
|
356
381
|
export function aegis256Encrypt(msg, ad, key, nonce = null, tagLen = 16) {
|
|
357
382
|
const actualNonce = nonce ?? randomBytes(AEGIS_256_NONCE_SIZE);
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
const adPadded = zeroPad(ad, 16);
|
|
361
|
-
for (let i = 0; i + 16 <= adPadded.length; i += 16) {
|
|
362
|
-
state.absorb(adPadded.subarray(i, i + 16));
|
|
363
|
-
}
|
|
364
|
-
const nonceSize = AEGIS_256_NONCE_SIZE;
|
|
365
|
-
const result = new Uint8Array(nonceSize + msg.length + tagLen);
|
|
383
|
+
const { ciphertext, tag } = aegis256EncryptDetached(msg, ad, key, actualNonce, tagLen);
|
|
384
|
+
const result = new Uint8Array(AEGIS_256_NONCE_SIZE + ciphertext.length + tagLen);
|
|
366
385
|
result.set(actualNonce, 0);
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
state.encTo(msg.subarray(i, i + 16), result.subarray(nonceSize + i, nonceSize + i + 16));
|
|
370
|
-
}
|
|
371
|
-
if (msg.length > fullBlocks) {
|
|
372
|
-
const lastBlock = zeroPad(msg.subarray(fullBlocks), 16);
|
|
373
|
-
const encBlock = state.enc(lastBlock);
|
|
374
|
-
result.set(encBlock.subarray(0, msg.length - fullBlocks), nonceSize + fullBlocks);
|
|
375
|
-
}
|
|
376
|
-
const tag = state.finalize(BigInt(ad.length * 8), BigInt(msg.length * 8), tagLen);
|
|
377
|
-
result.set(tag, nonceSize + msg.length);
|
|
386
|
+
result.set(ciphertext, AEGIS_256_NONCE_SIZE);
|
|
387
|
+
result.set(tag, AEGIS_256_NONCE_SIZE + ciphertext.length);
|
|
378
388
|
return result;
|
|
379
389
|
}
|
|
380
390
|
/**
|
|
@@ -407,11 +417,11 @@ export function aegis256Decrypt(sealed, ad, key, tagLen = 16) {
|
|
|
407
417
|
export function aegis256Mac(data, key, nonce = null, tagLen = 16) {
|
|
408
418
|
const state = new Aegis256State();
|
|
409
419
|
state.init(key, nonce ?? new Uint8Array(32));
|
|
410
|
-
const dataPadded = zeroPad(data,
|
|
411
|
-
for (let i = 0; i +
|
|
412
|
-
state.absorb(dataPadded
|
|
420
|
+
const dataPadded = zeroPad(data, RATE);
|
|
421
|
+
for (let i = 0; i + RATE <= dataPadded.length; i += RATE) {
|
|
422
|
+
state.absorb(dataPadded, i);
|
|
413
423
|
}
|
|
414
|
-
return state.finalize(
|
|
424
|
+
return state.finalize(data.length, tagLen, tagLen);
|
|
415
425
|
}
|
|
416
426
|
/**
|
|
417
427
|
* Verifies a MAC computed using AEGIS-256.
|
|
@@ -442,4 +452,3 @@ export function aegis256CreateKey() {
|
|
|
442
452
|
export function aegis256CreateNonce() {
|
|
443
453
|
return randomBytes(AEGIS_256_NONCE_SIZE);
|
|
444
454
|
}
|
|
445
|
-
//# sourceMappingURL=aegis256.js.map
|