aegis-aead 0.2.1 → 0.2.2
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 +4 -2
- package/dist/aegis128l-bs.d.ts +13 -70
- package/dist/aegis128l-bs.d.ts.map +1 -1
- package/dist/aegis128l-bs.js +67 -174
- package/dist/aegis128l-bs.js.map +1 -1
- package/dist/aegis256-bs.d.ts +15 -119
- package/dist/aegis256-bs.d.ts.map +1 -1
- package/dist/aegis256-bs.js +73 -184
- package/dist/aegis256-bs.js.map +1 -1
- package/dist/aes-bs.d.ts +16 -0
- package/dist/aes-bs.d.ts.map +1 -1
- package/dist/aes-bs.js +173 -99
- package/dist/aes-bs.js.map +1 -1
- package/package.json +3 -2
- package/src/aegis128l-bs.ts +69 -178
- package/src/aegis256-bs.ts +79 -185
- package/src/aes-bs.ts +187 -106
package/README.md
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AEGIS for JavaScript
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/aegis-aead)
|
|
4
4
|
[](https://github.com/jedisct1/js-aegis-aead/actions/workflows/ci.yml)
|
|
5
5
|
|
|
6
|
+
[View on npm](https://www.npmjs.com/package/aegis-aead)
|
|
7
|
+
|
|
6
8
|
A compact, zero-dependency JavaScript/TypeScript implementation of [AEGIS](https://datatracker.ietf.org/doc/draft-irtf-cfrg-aegis-aead/), a family of fast, secure authenticated encryption algorithms.
|
|
7
9
|
|
|
8
10
|
AEGIS provides both encryption with authentication and standalone MAC functionality, with a simple API that makes it hard to misuse.
|
|
9
11
|
|
|
10
12
|
## Table of Contents
|
|
11
13
|
|
|
12
|
-
- [
|
|
14
|
+
- [AEGIS for JavaScript](#aegis-for-javascript)
|
|
13
15
|
- [Table of Contents](#table-of-contents)
|
|
14
16
|
- [Installation](#installation)
|
|
15
17
|
- [Quick Start](#quick-start)
|
package/dist/aegis128l-bs.d.ts
CHANGED
|
@@ -4,37 +4,31 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
6
|
* Bitsliced AEGIS-128L cipher state.
|
|
7
|
-
*
|
|
7
|
+
* The state is kept in packed bitsliced form between operations so that
|
|
8
|
+
* pack/unpack does not need to be applied at every round.
|
|
8
9
|
*/
|
|
9
10
|
export declare class Aegis128LBsState {
|
|
10
11
|
private st;
|
|
11
12
|
private st1;
|
|
13
|
+
private constantInput;
|
|
12
14
|
private tmp0;
|
|
13
15
|
private tmp1;
|
|
14
16
|
private z0;
|
|
15
17
|
private z1;
|
|
16
18
|
constructor();
|
|
17
|
-
/**
|
|
18
|
-
* AEGIS round function: applies AES round to all blocks and rotates.
|
|
19
|
-
* st[i] = AES(st[i]) ^ st[(i-1) mod 8]
|
|
20
|
-
*/
|
|
21
|
-
private aegisRound;
|
|
22
|
-
/**
|
|
23
|
-
* AEGIS round function with constant input (used in packed mode).
|
|
24
|
-
*/
|
|
25
19
|
private aegisRoundPacked;
|
|
26
|
-
/**
|
|
27
|
-
* Pack constant input for blocks 0 and 4.
|
|
28
|
-
*/
|
|
29
20
|
private packConstantInput;
|
|
30
21
|
/**
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
*
|
|
22
|
+
* Extract the keystream blocks z0 and z1 directly from the packed state.
|
|
23
|
+
*
|
|
24
|
+
* z0 = S6 ^ S1 ^ (S2 & S3)
|
|
25
|
+
* z1 = S2 ^ S5 ^ (S6 & S7)
|
|
26
|
+
*
|
|
27
|
+
* The formula is evaluated lane-wise on the packed state, the result is
|
|
28
|
+
* placed in positions 0 (z0) and 4 (z1), then unpack04 extracts the two
|
|
29
|
+
* AES blocks.
|
|
36
30
|
*/
|
|
37
|
-
private
|
|
31
|
+
private keystreamPacked;
|
|
38
32
|
/**
|
|
39
33
|
* Initializes the state with a key and nonce.
|
|
40
34
|
* @param key - 16-byte encryption key
|
|
@@ -70,15 +64,7 @@ export declare class Aegis128LBsState {
|
|
|
70
64
|
* @returns 32-byte plaintext block
|
|
71
65
|
*/
|
|
72
66
|
dec(ci: Uint8Array): Uint8Array;
|
|
73
|
-
/**
|
|
74
|
-
* Encrypts a 32-byte plaintext block in-place.
|
|
75
|
-
* @param block - 32-byte buffer (plaintext in, ciphertext out)
|
|
76
|
-
*/
|
|
77
67
|
encInPlace(block: Uint8Array): void;
|
|
78
|
-
/**
|
|
79
|
-
* Decrypts a 32-byte ciphertext block in-place.
|
|
80
|
-
* @param block - 32-byte buffer (ciphertext in, plaintext out)
|
|
81
|
-
*/
|
|
82
68
|
decInPlace(block: Uint8Array): void;
|
|
83
69
|
/**
|
|
84
70
|
* Decrypts a partial (final) ciphertext block smaller than 32 bytes.
|
|
@@ -120,24 +106,10 @@ export declare function aegis128LBsEncryptDetached(msg: Uint8Array, ad: Uint8Arr
|
|
|
120
106
|
export declare function aegis128LBsDecryptDetached(ct: Uint8Array, tag: Uint8Array, ad: Uint8Array, key: Uint8Array, nonce: Uint8Array): Uint8Array | null;
|
|
121
107
|
/**
|
|
122
108
|
* Encrypts a message in-place using bitsliced AEGIS-128L (detached mode).
|
|
123
|
-
* The input buffer is modified to contain the ciphertext.
|
|
124
|
-
* @param data - Buffer containing plaintext (will be overwritten with ciphertext)
|
|
125
|
-
* @param ad - Associated data (authenticated but not encrypted)
|
|
126
|
-
* @param key - 16-byte encryption key
|
|
127
|
-
* @param nonce - 16-byte nonce (must be unique per message with the same key)
|
|
128
|
-
* @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
|
|
129
|
-
* @returns Authentication tag
|
|
130
109
|
*/
|
|
131
110
|
export declare function aegis128LBsEncryptDetachedInPlace(data: Uint8Array, ad: Uint8Array, key: Uint8Array, nonce: Uint8Array, tagLen?: 16 | 32): Uint8Array;
|
|
132
111
|
/**
|
|
133
112
|
* Decrypts a message in-place using bitsliced AEGIS-128L (detached mode).
|
|
134
|
-
* The input buffer is modified to contain the plaintext (or zeroed on failure).
|
|
135
|
-
* @param data - Buffer containing ciphertext (will be overwritten with plaintext)
|
|
136
|
-
* @param tag - Authentication tag (16 or 32 bytes)
|
|
137
|
-
* @param ad - Associated data (must match what was used during encryption)
|
|
138
|
-
* @param key - 16-byte encryption key
|
|
139
|
-
* @param nonce - 16-byte nonce (must match what was used during encryption)
|
|
140
|
-
* @returns True if authentication succeeds, false otherwise
|
|
141
113
|
*/
|
|
142
114
|
export declare function aegis128LBsDecryptDetachedInPlace(data: Uint8Array, tag: Uint8Array, ad: Uint8Array, key: Uint8Array, nonce: Uint8Array): boolean;
|
|
143
115
|
export declare const AEGIS_128L_BS_NONCE_SIZE = 16;
|
|
@@ -145,50 +117,21 @@ export declare const AEGIS_128L_BS_KEY_SIZE = 16;
|
|
|
145
117
|
/**
|
|
146
118
|
* Encrypts a message using bitsliced AEGIS-128L.
|
|
147
119
|
* Returns a single buffer containing nonce || ciphertext || tag.
|
|
148
|
-
* @param msg - Plaintext message
|
|
149
|
-
* @param ad - Associated data (authenticated but not encrypted)
|
|
150
|
-
* @param key - 16-byte encryption key
|
|
151
|
-
* @param nonce - 16-byte nonce (optional, generates random nonce if not provided)
|
|
152
|
-
* @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
|
|
153
|
-
* @returns Concatenated nonce || ciphertext || tag
|
|
154
120
|
*/
|
|
155
121
|
export declare function aegis128LBsEncrypt(msg: Uint8Array, ad: Uint8Array, key: Uint8Array, nonce?: Uint8Array | null, tagLen?: 16 | 32): Uint8Array;
|
|
156
122
|
/**
|
|
157
123
|
* Decrypts a message using bitsliced AEGIS-128L.
|
|
158
124
|
* Expects input as nonce || ciphertext || tag.
|
|
159
|
-
* @param sealed - Concatenated nonce || ciphertext || tag
|
|
160
|
-
* @param ad - Associated data (must match what was used during encryption)
|
|
161
|
-
* @param key - 16-byte encryption key
|
|
162
|
-
* @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
|
|
163
|
-
* @returns Decrypted plaintext, or null if authentication fails
|
|
164
125
|
*/
|
|
165
126
|
export declare function aegis128LBsDecrypt(sealed: Uint8Array, ad: Uint8Array, key: Uint8Array, tagLen?: 16 | 32): Uint8Array | null;
|
|
166
127
|
/**
|
|
167
|
-
* Computes a MAC
|
|
168
|
-
* @param data - Data to authenticate
|
|
169
|
-
* @param key - 16-byte key
|
|
170
|
-
* @param nonce - 16-byte nonce (optional, uses zero nonce if null)
|
|
171
|
-
* @param tagLen - Tag length: 16 or 32 bytes (default: 16)
|
|
172
|
-
* @returns Authentication tag
|
|
128
|
+
* Computes a MAC using bitsliced AEGIS-128L.
|
|
173
129
|
*/
|
|
174
130
|
export declare function aegis128LBsMac(data: Uint8Array, key: Uint8Array, nonce?: Uint8Array | null, tagLen?: 16 | 32): Uint8Array;
|
|
175
131
|
/**
|
|
176
132
|
* Verifies a MAC computed using bitsliced AEGIS-128L.
|
|
177
|
-
* @param data - Data to verify
|
|
178
|
-
* @param tag - Expected authentication tag (16 or 32 bytes)
|
|
179
|
-
* @param key - 16-byte key
|
|
180
|
-
* @param nonce - 16-byte nonce (optional, uses zero nonce if null)
|
|
181
|
-
* @returns True if the tag is valid, false otherwise
|
|
182
133
|
*/
|
|
183
134
|
export declare function aegis128LBsMacVerify(data: Uint8Array, tag: Uint8Array, key: Uint8Array, nonce?: Uint8Array | null): boolean;
|
|
184
|
-
/**
|
|
185
|
-
* Generates a random 16-byte key for bitsliced AEGIS-128L.
|
|
186
|
-
* @returns 16-byte encryption key
|
|
187
|
-
*/
|
|
188
135
|
export declare function aegis128LBsCreateKey(): Uint8Array;
|
|
189
|
-
/**
|
|
190
|
-
* Generates a random 16-byte nonce for bitsliced AEGIS-128L.
|
|
191
|
-
* @returns 16-byte nonce
|
|
192
|
-
*/
|
|
193
136
|
export declare function aegis128LBsCreateNonce(): Uint8Array;
|
|
194
137
|
//# sourceMappingURL=aegis128l-bs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aegis128l-bs.d.ts","sourceRoot":"","sources":["../src/aegis128l-bs.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"aegis128l-bs.d.ts","sourceRoot":"","sources":["../src/aegis128l-bs.ts"],"names":[],"mappings":"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"}
|
package/dist/aegis128l-bs.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Provides constant-time operation by processing all 8 state blocks simultaneously.
|
|
4
4
|
*/
|
|
5
5
|
import { constantTimeEqual, zeroPad } from "./aes.js";
|
|
6
|
-
import { aesRound, blockFromBytes, blocksPut, blocksRotr, blocksXor, blockToBytes, blockXor, createAesBlock, createAesBlocks, pack, pack04, unpack, wordIdx, } from "./aes-bs.js";
|
|
6
|
+
import { aesRound, blockFromBytes, blocksPut, blocksRotr, blocksXor, blockToBytes, blockXor, createAesBlock, createAesBlocks, pack, pack04, unpack, unpack04, wordIdx, } from "./aes-bs.js";
|
|
7
7
|
import { randomBytes } from "./random.js";
|
|
8
8
|
const RATE = 32;
|
|
9
9
|
const C0 = new Uint32Array([
|
|
@@ -14,77 +14,65 @@ const C1 = new Uint32Array([
|
|
|
14
14
|
]);
|
|
15
15
|
/**
|
|
16
16
|
* Bitsliced AEGIS-128L cipher state.
|
|
17
|
-
*
|
|
17
|
+
* The state is kept in packed bitsliced form between operations so that
|
|
18
|
+
* pack/unpack does not need to be applied at every round.
|
|
18
19
|
*/
|
|
19
20
|
export class Aegis128LBsState {
|
|
20
21
|
constructor() {
|
|
21
22
|
this.st = createAesBlocks();
|
|
22
23
|
this.st1 = createAesBlocks();
|
|
24
|
+
this.constantInput = createAesBlocks();
|
|
23
25
|
this.tmp0 = createAesBlock();
|
|
24
26
|
this.tmp1 = createAesBlock();
|
|
25
27
|
this.z0 = createAesBlock();
|
|
26
28
|
this.z1 = createAesBlock();
|
|
27
29
|
}
|
|
28
|
-
|
|
29
|
-
* AEGIS round function: applies AES round to all blocks and rotates.
|
|
30
|
-
* st[i] = AES(st[i]) ^ st[(i-1) mod 8]
|
|
31
|
-
*/
|
|
32
|
-
aegisRound() {
|
|
33
|
-
const st = this.st;
|
|
34
|
-
const st1 = this.st1;
|
|
35
|
-
st1.set(st);
|
|
36
|
-
pack(st1);
|
|
37
|
-
aesRound(st1);
|
|
38
|
-
unpack(st1);
|
|
39
|
-
for (let i = 0; i < 8; i++) {
|
|
40
|
-
const prev = (i + 7) % 8;
|
|
41
|
-
st[wordIdx(i, 0)] = (st[wordIdx(i, 0)] ^ st1[wordIdx(prev, 0)]) >>> 0;
|
|
42
|
-
st[wordIdx(i, 1)] = (st[wordIdx(i, 1)] ^ st1[wordIdx(prev, 1)]) >>> 0;
|
|
43
|
-
st[wordIdx(i, 2)] = (st[wordIdx(i, 2)] ^ st1[wordIdx(prev, 2)]) >>> 0;
|
|
44
|
-
st[wordIdx(i, 3)] = (st[wordIdx(i, 3)] ^ st1[wordIdx(prev, 3)]) >>> 0;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* AEGIS round function with constant input (used in packed mode).
|
|
49
|
-
*/
|
|
50
|
-
aegisRoundPacked(constantInput) {
|
|
30
|
+
aegisRoundPacked() {
|
|
51
31
|
const st = this.st;
|
|
52
32
|
const st1 = this.st1;
|
|
53
33
|
st1.set(st);
|
|
54
34
|
aesRound(st1);
|
|
55
35
|
blocksRotr(st1);
|
|
56
36
|
blocksXor(st, st1);
|
|
57
|
-
blocksXor(st, constantInput);
|
|
37
|
+
blocksXor(st, this.constantInput);
|
|
58
38
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
*/
|
|
62
|
-
packConstantInput(out, m0, m1) {
|
|
39
|
+
packConstantInput(m0, m1) {
|
|
40
|
+
const out = this.constantInput;
|
|
63
41
|
out.fill(0);
|
|
64
42
|
blocksPut(out, m0, 0);
|
|
65
43
|
blocksPut(out, m1, 4);
|
|
66
44
|
pack04(out);
|
|
67
45
|
}
|
|
68
46
|
/**
|
|
69
|
-
*
|
|
47
|
+
* Extract the keystream blocks z0 and z1 directly from the packed state.
|
|
48
|
+
*
|
|
49
|
+
* z0 = S6 ^ S1 ^ (S2 & S3)
|
|
50
|
+
* z1 = S2 ^ S5 ^ (S6 & S7)
|
|
51
|
+
*
|
|
52
|
+
* The formula is evaluated lane-wise on the packed state, the result is
|
|
53
|
+
* placed in positions 0 (z0) and 4 (z1), then unpack04 extracts the two
|
|
54
|
+
* AES blocks.
|
|
70
55
|
*/
|
|
71
|
-
|
|
56
|
+
keystreamPacked() {
|
|
72
57
|
const st = this.st;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
this.
|
|
87
|
-
|
|
58
|
+
const z = this.st1;
|
|
59
|
+
for (let i = 0; i < 32; i++) {
|
|
60
|
+
const x = st[i];
|
|
61
|
+
z[i] =
|
|
62
|
+
((x & 0x02020202) << 6) ^
|
|
63
|
+
((x & 0x40404040) << 1) ^
|
|
64
|
+
((x & (x >>> 1) & 0x10101010) << 3) ^
|
|
65
|
+
((x & 0x20202020) >>> 2) ^
|
|
66
|
+
((x & 0x04040404) << 1) ^
|
|
67
|
+
((x & (x >>> 1) & 0x01010101) << 3);
|
|
68
|
+
}
|
|
69
|
+
unpack04(z);
|
|
70
|
+
const z0 = this.z0;
|
|
71
|
+
const z1 = this.z1;
|
|
72
|
+
for (let i = 0; i < 4; i++) {
|
|
73
|
+
z0[i] = z[wordIdx(0, i)];
|
|
74
|
+
z1[i] = z[wordIdx(4, i)];
|
|
75
|
+
}
|
|
88
76
|
}
|
|
89
77
|
/**
|
|
90
78
|
* Initializes the state with a key and nonce.
|
|
@@ -110,13 +98,11 @@ export class Aegis128LBsState {
|
|
|
110
98
|
blocksPut(this.st, kc0, 5);
|
|
111
99
|
blocksPut(this.st, kc1, 6);
|
|
112
100
|
blocksPut(this.st, kc0, 7);
|
|
113
|
-
|
|
114
|
-
this.packConstantInput(constantInput, n, k);
|
|
101
|
+
this.packConstantInput(n, k);
|
|
115
102
|
pack(this.st);
|
|
116
103
|
for (let i = 0; i < 10; i++) {
|
|
117
|
-
this.aegisRoundPacked(
|
|
104
|
+
this.aegisRoundPacked();
|
|
118
105
|
}
|
|
119
|
-
unpack(this.st);
|
|
120
106
|
}
|
|
121
107
|
/**
|
|
122
108
|
* Absorbs a 32-byte associated data block into the state.
|
|
@@ -127,7 +113,8 @@ export class Aegis128LBsState {
|
|
|
127
113
|
const msg1 = this.tmp1;
|
|
128
114
|
blockFromBytes(msg0, ai.subarray(0, 16));
|
|
129
115
|
blockFromBytes(msg1, ai.subarray(16, 32));
|
|
130
|
-
this.
|
|
116
|
+
this.packConstantInput(msg0, msg1);
|
|
117
|
+
this.aegisRoundPacked();
|
|
131
118
|
}
|
|
132
119
|
/**
|
|
133
120
|
* Encrypts a 32-byte plaintext block and writes to output buffer.
|
|
@@ -135,34 +122,17 @@ export class Aegis128LBsState {
|
|
|
135
122
|
* @param out - 32-byte output buffer
|
|
136
123
|
*/
|
|
137
124
|
encTo(xi, out) {
|
|
138
|
-
const st = this.st;
|
|
139
|
-
const z0 = this.z0;
|
|
140
|
-
const z1 = this.z1;
|
|
141
125
|
const t0 = this.tmp0;
|
|
142
126
|
const t1 = this.tmp1;
|
|
143
|
-
|
|
144
|
-
z0[i] =
|
|
145
|
-
(st[wordIdx(6, i)] ^
|
|
146
|
-
st[wordIdx(1, i)] ^
|
|
147
|
-
(st[wordIdx(2, i)] & st[wordIdx(3, i)])) >>>
|
|
148
|
-
0;
|
|
149
|
-
}
|
|
150
|
-
for (let i = 0; i < 4; i++) {
|
|
151
|
-
z1[i] =
|
|
152
|
-
(st[wordIdx(2, i)] ^
|
|
153
|
-
st[wordIdx(5, i)] ^
|
|
154
|
-
(st[wordIdx(6, i)] & st[wordIdx(7, i)])) >>>
|
|
155
|
-
0;
|
|
156
|
-
}
|
|
127
|
+
this.keystreamPacked();
|
|
157
128
|
blockFromBytes(t0, xi.subarray(0, 16));
|
|
158
129
|
blockFromBytes(t1, xi.subarray(16, 32));
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
blockXor(
|
|
162
|
-
blockXor(
|
|
163
|
-
blockToBytes(out.subarray(0, 16),
|
|
164
|
-
blockToBytes(out.subarray(16, 32),
|
|
165
|
-
this.update(t0, t1);
|
|
130
|
+
this.packConstantInput(t0, t1);
|
|
131
|
+
this.aegisRoundPacked();
|
|
132
|
+
blockXor(t0, t0, this.z0);
|
|
133
|
+
blockXor(t1, t1, this.z1);
|
|
134
|
+
blockToBytes(out.subarray(0, 16), t0);
|
|
135
|
+
blockToBytes(out.subarray(16, 32), t1);
|
|
166
136
|
}
|
|
167
137
|
/**
|
|
168
138
|
* Encrypts a 32-byte plaintext block.
|
|
@@ -180,28 +150,15 @@ export class Aegis128LBsState {
|
|
|
180
150
|
* @param out - 32-byte output buffer
|
|
181
151
|
*/
|
|
182
152
|
decTo(ci, out) {
|
|
183
|
-
const st = this.st;
|
|
184
153
|
const msg0 = this.tmp0;
|
|
185
154
|
const msg1 = this.tmp1;
|
|
186
155
|
blockFromBytes(msg0, ci.subarray(0, 16));
|
|
187
156
|
blockFromBytes(msg1, ci.subarray(16, 32));
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
(st[wordIdx(2, i)] & st[wordIdx(3, i)])) >>>
|
|
194
|
-
0;
|
|
195
|
-
}
|
|
196
|
-
for (let i = 0; i < 4; i++) {
|
|
197
|
-
msg1[i] =
|
|
198
|
-
(msg1[i] ^
|
|
199
|
-
st[wordIdx(2, i)] ^
|
|
200
|
-
st[wordIdx(5, i)] ^
|
|
201
|
-
(st[wordIdx(6, i)] & st[wordIdx(7, i)])) >>>
|
|
202
|
-
0;
|
|
203
|
-
}
|
|
204
|
-
this.update(msg0, msg1);
|
|
157
|
+
this.keystreamPacked();
|
|
158
|
+
blockXor(msg0, msg0, this.z0);
|
|
159
|
+
blockXor(msg1, msg1, this.z1);
|
|
160
|
+
this.packConstantInput(msg0, msg1);
|
|
161
|
+
this.aegisRoundPacked();
|
|
205
162
|
blockToBytes(out.subarray(0, 16), msg0);
|
|
206
163
|
blockToBytes(out.subarray(16, 32), msg1);
|
|
207
164
|
}
|
|
@@ -215,17 +172,9 @@ export class Aegis128LBsState {
|
|
|
215
172
|
this.decTo(ci, out);
|
|
216
173
|
return out;
|
|
217
174
|
}
|
|
218
|
-
/**
|
|
219
|
-
* Encrypts a 32-byte plaintext block in-place.
|
|
220
|
-
* @param block - 32-byte buffer (plaintext in, ciphertext out)
|
|
221
|
-
*/
|
|
222
175
|
encInPlace(block) {
|
|
223
176
|
this.encTo(block, block);
|
|
224
177
|
}
|
|
225
|
-
/**
|
|
226
|
-
* Decrypts a 32-byte ciphertext block in-place.
|
|
227
|
-
* @param block - 32-byte buffer (ciphertext in, plaintext out)
|
|
228
|
-
*/
|
|
229
178
|
decInPlace(block) {
|
|
230
179
|
this.decTo(block, block);
|
|
231
180
|
}
|
|
@@ -235,28 +184,14 @@ export class Aegis128LBsState {
|
|
|
235
184
|
* @returns Decrypted plaintext of the same length
|
|
236
185
|
*/
|
|
237
186
|
decPartial(cn) {
|
|
238
|
-
const st = this.st;
|
|
239
187
|
const msg0 = this.tmp0;
|
|
240
188
|
const msg1 = this.tmp1;
|
|
241
189
|
const padded = zeroPad(cn, RATE);
|
|
242
190
|
blockFromBytes(msg0, padded.subarray(0, 16));
|
|
243
191
|
blockFromBytes(msg1, padded.subarray(16, 32));
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
st[wordIdx(6, i)] ^
|
|
248
|
-
st[wordIdx(1, i)] ^
|
|
249
|
-
(st[wordIdx(2, i)] & st[wordIdx(3, i)])) >>>
|
|
250
|
-
0;
|
|
251
|
-
}
|
|
252
|
-
for (let i = 0; i < 4; i++) {
|
|
253
|
-
msg1[i] =
|
|
254
|
-
(msg1[i] ^
|
|
255
|
-
st[wordIdx(2, i)] ^
|
|
256
|
-
st[wordIdx(5, i)] ^
|
|
257
|
-
(st[wordIdx(6, i)] & st[wordIdx(7, i)])) >>>
|
|
258
|
-
0;
|
|
259
|
-
}
|
|
192
|
+
this.keystreamPacked();
|
|
193
|
+
blockXor(msg0, msg0, this.z0);
|
|
194
|
+
blockXor(msg1, msg1, this.z1);
|
|
260
195
|
const pad = new Uint8Array(RATE);
|
|
261
196
|
blockToBytes(pad.subarray(0, 16), msg0);
|
|
262
197
|
blockToBytes(pad.subarray(16, 32), msg1);
|
|
@@ -264,8 +199,8 @@ export class Aegis128LBsState {
|
|
|
264
199
|
pad.fill(0, cn.length);
|
|
265
200
|
blockFromBytes(msg0, pad.subarray(0, 16));
|
|
266
201
|
blockFromBytes(msg1, pad.subarray(16, 32));
|
|
267
|
-
this.
|
|
268
|
-
this.
|
|
202
|
+
this.packConstantInput(msg0, msg1);
|
|
203
|
+
this.aegisRoundPacked();
|
|
269
204
|
return xn;
|
|
270
205
|
}
|
|
271
206
|
/**
|
|
@@ -282,17 +217,18 @@ export class Aegis128LBsState {
|
|
|
282
217
|
tmp[1] = Math.floor((adLen * 8) / 0x100000000) >>> 0;
|
|
283
218
|
tmp[2] = ((msgLen * 8) & 0xffffffff) >>> 0;
|
|
284
219
|
tmp[3] = Math.floor((msgLen * 8) / 0x100000000) >>> 0;
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
tmp[
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
220
|
+
const unpacked = this.st1;
|
|
221
|
+
unpacked.set(st);
|
|
222
|
+
unpack(unpacked);
|
|
223
|
+
tmp[0] = (tmp[0] ^ unpacked[wordIdx(2, 0)]) >>> 0;
|
|
224
|
+
tmp[1] = (tmp[1] ^ unpacked[wordIdx(2, 1)]) >>> 0;
|
|
225
|
+
tmp[2] = (tmp[2] ^ unpacked[wordIdx(2, 2)]) >>> 0;
|
|
226
|
+
tmp[3] = (tmp[3] ^ unpacked[wordIdx(2, 3)]) >>> 0;
|
|
227
|
+
this.packConstantInput(tmp, tmp);
|
|
292
228
|
for (let i = 0; i < 7; i++) {
|
|
293
|
-
this.aegisRoundPacked(
|
|
229
|
+
this.aegisRoundPacked();
|
|
294
230
|
}
|
|
295
|
-
unpack(
|
|
231
|
+
unpack(st);
|
|
296
232
|
if (tagLen === 16) {
|
|
297
233
|
const tag = new Uint8Array(16);
|
|
298
234
|
const tagBlock = createAesBlock();
|
|
@@ -399,13 +335,6 @@ export function aegis128LBsDecryptDetached(ct, tag, ad, key, nonce) {
|
|
|
399
335
|
}
|
|
400
336
|
/**
|
|
401
337
|
* Encrypts a message in-place using bitsliced AEGIS-128L (detached mode).
|
|
402
|
-
* The input buffer is modified to contain the ciphertext.
|
|
403
|
-
* @param data - Buffer containing plaintext (will be overwritten with ciphertext)
|
|
404
|
-
* @param ad - Associated data (authenticated but not encrypted)
|
|
405
|
-
* @param key - 16-byte encryption key
|
|
406
|
-
* @param nonce - 16-byte nonce (must be unique per message with the same key)
|
|
407
|
-
* @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
|
|
408
|
-
* @returns Authentication tag
|
|
409
338
|
*/
|
|
410
339
|
export function aegis128LBsEncryptDetachedInPlace(data, ad, key, nonce, tagLen = 16) {
|
|
411
340
|
const state = new Aegis128LBsState();
|
|
@@ -429,13 +358,6 @@ export function aegis128LBsEncryptDetachedInPlace(data, ad, key, nonce, tagLen =
|
|
|
429
358
|
}
|
|
430
359
|
/**
|
|
431
360
|
* Decrypts a message in-place using bitsliced AEGIS-128L (detached mode).
|
|
432
|
-
* The input buffer is modified to contain the plaintext (or zeroed on failure).
|
|
433
|
-
* @param data - Buffer containing ciphertext (will be overwritten with plaintext)
|
|
434
|
-
* @param tag - Authentication tag (16 or 32 bytes)
|
|
435
|
-
* @param ad - Associated data (must match what was used during encryption)
|
|
436
|
-
* @param key - 16-byte encryption key
|
|
437
|
-
* @param nonce - 16-byte nonce (must match what was used during encryption)
|
|
438
|
-
* @returns True if authentication succeeds, false otherwise
|
|
439
361
|
*/
|
|
440
362
|
export function aegis128LBsDecryptDetachedInPlace(data, tag, ad, key, nonce) {
|
|
441
363
|
const tagLen = tag.length;
|
|
@@ -467,12 +389,6 @@ export const AEGIS_128L_BS_KEY_SIZE = 16;
|
|
|
467
389
|
/**
|
|
468
390
|
* Encrypts a message using bitsliced AEGIS-128L.
|
|
469
391
|
* Returns a single buffer containing nonce || ciphertext || tag.
|
|
470
|
-
* @param msg - Plaintext message
|
|
471
|
-
* @param ad - Associated data (authenticated but not encrypted)
|
|
472
|
-
* @param key - 16-byte encryption key
|
|
473
|
-
* @param nonce - 16-byte nonce (optional, generates random nonce if not provided)
|
|
474
|
-
* @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
|
|
475
|
-
* @returns Concatenated nonce || ciphertext || tag
|
|
476
392
|
*/
|
|
477
393
|
export function aegis128LBsEncrypt(msg, ad, key, nonce = null, tagLen = 16) {
|
|
478
394
|
const actualNonce = nonce ?? randomBytes(AEGIS_128L_BS_NONCE_SIZE);
|
|
@@ -486,11 +402,6 @@ export function aegis128LBsEncrypt(msg, ad, key, nonce = null, tagLen = 16) {
|
|
|
486
402
|
/**
|
|
487
403
|
* Decrypts a message using bitsliced AEGIS-128L.
|
|
488
404
|
* Expects input as nonce || ciphertext || tag.
|
|
489
|
-
* @param sealed - Concatenated nonce || ciphertext || tag
|
|
490
|
-
* @param ad - Associated data (must match what was used during encryption)
|
|
491
|
-
* @param key - 16-byte encryption key
|
|
492
|
-
* @param tagLen - Authentication tag length: 16 or 32 bytes (default: 16)
|
|
493
|
-
* @returns Decrypted plaintext, or null if authentication fails
|
|
494
405
|
*/
|
|
495
406
|
export function aegis128LBsDecrypt(sealed, ad, key, tagLen = 16) {
|
|
496
407
|
const nonceSize = AEGIS_128L_BS_NONCE_SIZE;
|
|
@@ -503,12 +414,7 @@ export function aegis128LBsDecrypt(sealed, ad, key, tagLen = 16) {
|
|
|
503
414
|
return aegis128LBsDecryptDetached(ct, tag, ad, key, nonce);
|
|
504
415
|
}
|
|
505
416
|
/**
|
|
506
|
-
* Computes a MAC
|
|
507
|
-
* @param data - Data to authenticate
|
|
508
|
-
* @param key - 16-byte key
|
|
509
|
-
* @param nonce - 16-byte nonce (optional, uses zero nonce if null)
|
|
510
|
-
* @param tagLen - Tag length: 16 or 32 bytes (default: 16)
|
|
511
|
-
* @returns Authentication tag
|
|
417
|
+
* Computes a MAC using bitsliced AEGIS-128L.
|
|
512
418
|
*/
|
|
513
419
|
export function aegis128LBsMac(data, key, nonce = null, tagLen = 16) {
|
|
514
420
|
const state = new Aegis128LBsState();
|
|
@@ -521,28 +427,15 @@ export function aegis128LBsMac(data, key, nonce = null, tagLen = 16) {
|
|
|
521
427
|
}
|
|
522
428
|
/**
|
|
523
429
|
* Verifies a MAC computed using bitsliced AEGIS-128L.
|
|
524
|
-
* @param data - Data to verify
|
|
525
|
-
* @param tag - Expected authentication tag (16 or 32 bytes)
|
|
526
|
-
* @param key - 16-byte key
|
|
527
|
-
* @param nonce - 16-byte nonce (optional, uses zero nonce if null)
|
|
528
|
-
* @returns True if the tag is valid, false otherwise
|
|
529
430
|
*/
|
|
530
431
|
export function aegis128LBsMacVerify(data, tag, key, nonce = null) {
|
|
531
432
|
const tagLen = tag.length;
|
|
532
433
|
const expectedTag = aegis128LBsMac(data, key, nonce, tagLen);
|
|
533
434
|
return constantTimeEqual(tag, expectedTag);
|
|
534
435
|
}
|
|
535
|
-
/**
|
|
536
|
-
* Generates a random 16-byte key for bitsliced AEGIS-128L.
|
|
537
|
-
* @returns 16-byte encryption key
|
|
538
|
-
*/
|
|
539
436
|
export function aegis128LBsCreateKey() {
|
|
540
437
|
return randomBytes(AEGIS_128L_BS_KEY_SIZE);
|
|
541
438
|
}
|
|
542
|
-
/**
|
|
543
|
-
* Generates a random 16-byte nonce for bitsliced AEGIS-128L.
|
|
544
|
-
* @returns 16-byte nonce
|
|
545
|
-
*/
|
|
546
439
|
export function aegis128LBsCreateNonce() {
|
|
547
440
|
return randomBytes(AEGIS_128L_BS_NONCE_SIZE);
|
|
548
441
|
}
|