aegis-aead 0.2.0 → 0.2.1
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 +152 -227
- package/dist/aegis128l-bs.d.ts +32 -0
- package/dist/aegis128l-bs.d.ts.map +1 -1
- package/dist/aegis128l-bs.js +79 -0
- package/dist/aegis128l-bs.js.map +1 -1
- package/dist/aegis128l.d.ts +32 -0
- package/dist/aegis128l.d.ts.map +1 -1
- package/dist/aegis128l.js +94 -0
- package/dist/aegis128l.js.map +1 -1
- package/dist/aegis128x.d.ts +42 -0
- package/dist/aegis128x.d.ts.map +1 -1
- package/dist/aegis128x.js +100 -0
- package/dist/aegis128x.js.map +1 -1
- package/dist/aegis256-bs.d.ts +32 -0
- package/dist/aegis256-bs.d.ts.map +1 -1
- package/dist/aegis256-bs.js +79 -0
- package/dist/aegis256-bs.js.map +1 -1
- package/dist/aegis256.d.ts +32 -0
- package/dist/aegis256.d.ts.map +1 -1
- package/dist/aegis256.js +79 -0
- package/dist/aegis256.js.map +1 -1
- package/dist/aegis256x.d.ts +42 -0
- package/dist/aegis256x.d.ts.map +1 -1
- package/dist/aegis256x.js +91 -0
- package/dist/aegis256x.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/aegis128l-bs.ts +107 -0
- package/src/aegis128l.ts +126 -0
- package/src/aegis128x.ts +168 -0
- package/src/aegis256-bs.ts +107 -0
- package/src/aegis256.ts +111 -0
- package/src/aegis256x.ts +155 -0
- package/src/index.ts +20 -0
package/README.md
CHANGED
|
@@ -7,6 +7,30 @@ A compact, zero-dependency JavaScript/TypeScript implementation of [AEGIS](https
|
|
|
7
7
|
|
|
8
8
|
AEGIS provides both encryption with authentication and standalone MAC functionality, with a simple API that makes it hard to misuse.
|
|
9
9
|
|
|
10
|
+
## Table of Contents
|
|
11
|
+
|
|
12
|
+
- [aegis-aead](#aegis-aead)
|
|
13
|
+
- [Table of Contents](#table-of-contents)
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Quick Start](#quick-start)
|
|
16
|
+
- [Choosing an Algorithm](#choosing-an-algorithm)
|
|
17
|
+
- [Usage Examples](#usage-examples)
|
|
18
|
+
- [Combined Mode](#combined-mode)
|
|
19
|
+
- [Detached Mode](#detached-mode)
|
|
20
|
+
- [In-Place Mode](#in-place-mode)
|
|
21
|
+
- [MAC (Message Authentication Code)](#mac-message-authentication-code)
|
|
22
|
+
- [API Overview](#api-overview)
|
|
23
|
+
- [Functions](#functions)
|
|
24
|
+
- [Parameters](#parameters)
|
|
25
|
+
- [Constants](#constants)
|
|
26
|
+
- [Parallel Variants (AEGIS-128X / AEGIS-256X)](#parallel-variants-aegis-128x--aegis-256x)
|
|
27
|
+
- [Security Considerations](#security-considerations)
|
|
28
|
+
- [Nonce Safety](#nonce-safety)
|
|
29
|
+
- [Tag Lengths](#tag-lengths)
|
|
30
|
+
- [Bitsliced Variants](#bitsliced-variants)
|
|
31
|
+
- [Compatibility](#compatibility)
|
|
32
|
+
- [Browser Example](#browser-example)
|
|
33
|
+
|
|
10
34
|
## Installation
|
|
11
35
|
|
|
12
36
|
```bash
|
|
@@ -15,32 +39,62 @@ bun add aegis-aead
|
|
|
15
39
|
npm install aegis-aead
|
|
16
40
|
```
|
|
17
41
|
|
|
18
|
-
##
|
|
19
|
-
|
|
20
|
-
### Encryption and Decryption
|
|
42
|
+
## Quick Start
|
|
21
43
|
|
|
22
44
|
```typescript
|
|
23
|
-
import {
|
|
24
|
-
aegis128LCreateKey,
|
|
25
|
-
aegis128LEncrypt,
|
|
26
|
-
aegis128LDecrypt
|
|
27
|
-
} from "aegis-aead";
|
|
45
|
+
import { aegis128LCreateKey, aegis128LEncrypt, aegis128LDecrypt } from "aegis-aead";
|
|
28
46
|
|
|
29
|
-
const key = aegis128LCreateKey();
|
|
47
|
+
const key = aegis128LCreateKey();
|
|
30
48
|
const message = new TextEncoder().encode("Hello, world!");
|
|
31
49
|
const associatedData = new TextEncoder().encode("metadata");
|
|
32
50
|
|
|
33
|
-
// Encrypt
|
|
34
|
-
// A random nonce is generated automatically
|
|
51
|
+
// Encrypt (nonce is generated automatically)
|
|
35
52
|
const sealed = aegis128LEncrypt(message, associatedData, key);
|
|
36
53
|
|
|
37
54
|
// Decrypt (returns null if authentication fails)
|
|
38
55
|
const decrypted = aegis128LDecrypt(sealed, associatedData, key);
|
|
39
56
|
```
|
|
40
57
|
|
|
58
|
+
## Choosing an Algorithm
|
|
59
|
+
|
|
60
|
+
| Algorithm | Key | Nonce | Best For |
|
|
61
|
+
| ------------- | -------- | -------- | ---------------------------------------- |
|
|
62
|
+
| AEGIS-128L | 16 bytes | 16 bytes | General use, high throughput |
|
|
63
|
+
| AEGIS-256 | 32 bytes | 32 bytes | Large nonce, unlimited messages |
|
|
64
|
+
| AEGIS-128X | 16 bytes | 16 bytes | Interop with native SIMD implementations |
|
|
65
|
+
| AEGIS-256X | 32 bytes | 32 bytes | Interop + large nonce |
|
|
66
|
+
| AEGIS-128L-BS | 16 bytes | 16 bytes | Side-channel protection |
|
|
67
|
+
| AEGIS-256-BS | 32 bytes | 32 bytes | Side-channel + large nonce |
|
|
68
|
+
|
|
69
|
+
Recommendations:
|
|
70
|
+
|
|
71
|
+
- Default choice: AEGIS-128L offers excellent performance with safe random nonces up to 2^48 messages
|
|
72
|
+
- Unlimited messages: AEGIS-256 when you need unlimited random nonces (32-byte nonce eliminates collision risk)
|
|
73
|
+
- Interoperability: AEGIS-128X/256X when exchanging data with native implementations using these variants
|
|
74
|
+
- Hostile environments: Bitsliced variants (-BS) when attackers may observe timing
|
|
75
|
+
|
|
76
|
+
Note: The X variants are designed for SIMD parallelism in native code. In JavaScript they offer no speed benefit but are provided for interoperability.
|
|
77
|
+
|
|
78
|
+
## Usage Examples
|
|
79
|
+
|
|
80
|
+
### Combined Mode
|
|
81
|
+
|
|
82
|
+
The simplest API: returns `nonce || ciphertext || tag` in one buffer.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { aegis128LCreateKey, aegis128LEncrypt, aegis128LDecrypt } from "aegis-aead";
|
|
86
|
+
|
|
87
|
+
const key = aegis128LCreateKey();
|
|
88
|
+
const message = new TextEncoder().encode("Hello, world!");
|
|
89
|
+
const ad = new TextEncoder().encode("metadata");
|
|
90
|
+
|
|
91
|
+
const sealed = aegis128LEncrypt(message, ad, key);
|
|
92
|
+
const decrypted = aegis128LDecrypt(sealed, ad, key);
|
|
93
|
+
```
|
|
94
|
+
|
|
41
95
|
### Detached Mode
|
|
42
96
|
|
|
43
|
-
|
|
97
|
+
When you need separate access to ciphertext and tag:
|
|
44
98
|
|
|
45
99
|
```typescript
|
|
46
100
|
import {
|
|
@@ -53,278 +107,149 @@ import {
|
|
|
53
107
|
const key = aegis128LCreateKey();
|
|
54
108
|
const nonce = aegis128LCreateNonce();
|
|
55
109
|
const message = new TextEncoder().encode("Hello, world!");
|
|
56
|
-
const
|
|
110
|
+
const ad = new TextEncoder().encode("metadata");
|
|
57
111
|
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
// Decrypt
|
|
62
|
-
const decrypted = aegis128LDecryptDetached(ciphertext, tag, associatedData, key, nonce);
|
|
112
|
+
const { ciphertext, tag } = aegis128LEncryptDetached(message, ad, key, nonce);
|
|
113
|
+
const decrypted = aegis128LDecryptDetached(ciphertext, tag, ad, key, nonce);
|
|
63
114
|
```
|
|
64
115
|
|
|
65
|
-
###
|
|
116
|
+
### In-Place Mode
|
|
117
|
+
|
|
118
|
+
Zero-copy encryption that modifies the buffer directly:
|
|
66
119
|
|
|
67
120
|
```typescript
|
|
68
121
|
import {
|
|
69
122
|
aegis128LCreateKey,
|
|
70
|
-
|
|
71
|
-
|
|
123
|
+
aegis128LCreateNonce,
|
|
124
|
+
aegis128LEncryptDetachedInPlace,
|
|
125
|
+
aegis128LDecryptDetachedInPlace
|
|
72
126
|
} from "aegis-aead";
|
|
73
127
|
|
|
74
128
|
const key = aegis128LCreateKey();
|
|
75
|
-
const
|
|
129
|
+
const nonce = aegis128LCreateNonce();
|
|
130
|
+
const data = new TextEncoder().encode("Hello, world!");
|
|
131
|
+
const ad = new TextEncoder().encode("metadata");
|
|
76
132
|
|
|
77
|
-
//
|
|
78
|
-
const tag =
|
|
133
|
+
// Encrypt: data is modified, tag is returned
|
|
134
|
+
const tag = aegis128LEncryptDetachedInPlace(data, ad, key, nonce);
|
|
79
135
|
|
|
80
|
-
//
|
|
81
|
-
const
|
|
136
|
+
// Decrypt: returns true if authentication succeeds
|
|
137
|
+
const success = aegis128LDecryptDetachedInPlace(data, tag, ad, key, nonce);
|
|
82
138
|
```
|
|
83
139
|
|
|
84
|
-
|
|
140
|
+
### MAC (Message Authentication Code)
|
|
85
141
|
|
|
86
|
-
|
|
87
|
-
| ------------- | -------- | ---------- | ---------- | ---------------------------------- |
|
|
88
|
-
| AEGIS-128L | 16 bytes | 16 bytes | 32 bytes | High throughput on 64-bit CPUs |
|
|
89
|
-
| AEGIS-256 | 32 bytes | 32 bytes | 16 bytes | 256-bit security level |
|
|
90
|
-
| AEGIS-128X | 16 bytes | 16 bytes | 32×D bytes | Multi-lane AEGIS-128L (D = degree) |
|
|
91
|
-
| AEGIS-256X | 32 bytes | 32 bytes | 16×D bytes | Multi-lane AEGIS-256 (D = degree) |
|
|
92
|
-
| AEGIS-128L-BS | 16 bytes | 16 bytes | 32 bytes | Bitsliced |
|
|
93
|
-
| AEGIS-256-BS | 32 bytes | 32 bytes | 16 bytes | Bitsliced |
|
|
142
|
+
Authenticate data without encrypting:
|
|
94
143
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
The `-BS` (bitsliced) variants provide protection against cache-timing side-channel attacks at the cost of ~20% performance overhead. They process AES operations without lookup tables, making execution time independent of the key and data values.
|
|
144
|
+
```typescript
|
|
145
|
+
import { aegis128LCreateKey, aegis128LMac, aegis128LMacVerify } from "aegis-aead";
|
|
98
146
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
- The key holder may encrypt or decrypt attacker-controlled data
|
|
102
|
-
- Maximum side-channel resistance is required
|
|
147
|
+
const key = aegis128LCreateKey();
|
|
148
|
+
const data = new TextEncoder().encode("data to authenticate");
|
|
103
149
|
|
|
104
|
-
|
|
150
|
+
const tag = aegis128LMac(data, key);
|
|
151
|
+
const valid = aegis128LMacVerify(data, tag, key);
|
|
152
|
+
```
|
|
105
153
|
|
|
106
|
-
|
|
154
|
+
## API Overview
|
|
107
155
|
|
|
108
|
-
|
|
156
|
+
All AEGIS variants follow the same API pattern. Replace `aegis128L` with your chosen algorithm (`aegis256`, `aegis128X2`, `aegis128X4`, `aegis256X2`, `aegis256X4`, `aegis128LBs`, `aegis256Bs`).
|
|
109
157
|
|
|
110
|
-
|
|
111
|
-
- AEGIS-256/256X: No practical limits on the number of messages per key
|
|
158
|
+
### Functions
|
|
112
159
|
|
|
113
|
-
|
|
160
|
+
| Function | Description |
|
|
161
|
+
| ------------------------------------------------------- | -------------------------------------------------- |
|
|
162
|
+
| `createKey()` | Generate a random key |
|
|
163
|
+
| `createNonce()` | Generate a random nonce |
|
|
164
|
+
| `encrypt(msg, ad, key, nonce?, tagLen?)` | Encrypt, returns `nonce \|\| ciphertext \|\| tag` |
|
|
165
|
+
| `decrypt(sealed, ad, key, tagLen?)` | Decrypt combined output, returns `null` on failure |
|
|
166
|
+
| `encryptDetached(msg, ad, key, nonce, tagLen?)` | Encrypt, returns `{ ciphertext, tag }` |
|
|
167
|
+
| `decryptDetached(ct, tag, ad, key, nonce)` | Decrypt detached, returns `null` on failure |
|
|
168
|
+
| `encryptDetachedInPlace(data, ad, key, nonce, tagLen?)` | Encrypt in-place, returns tag |
|
|
169
|
+
| `decryptDetachedInPlace(data, tag, ad, key, nonce)` | Decrypt in-place, returns `boolean` |
|
|
170
|
+
| `mac(data, key, nonce?, tagLen?)` | Generate MAC tag |
|
|
171
|
+
| `macVerify(data, tag, key, nonce?)` | Verify MAC tag |
|
|
114
172
|
|
|
115
|
-
|
|
173
|
+
### Parameters
|
|
116
174
|
|
|
117
|
-
-
|
|
118
|
-
-
|
|
175
|
+
- msg/data: `Uint8Array` - Data to encrypt/authenticate
|
|
176
|
+
- ad: `Uint8Array` - Associated data (authenticated but not encrypted)
|
|
177
|
+
- key: `Uint8Array` - Encryption key (16 or 32 bytes depending on algorithm)
|
|
178
|
+
- nonce: `Uint8Array` - Number used once (auto-generated if omitted in combined mode)
|
|
179
|
+
- tagLen: `number` - Authentication tag length: `16` (default) or `32`
|
|
119
180
|
|
|
120
|
-
|
|
181
|
+
### Constants
|
|
121
182
|
|
|
122
|
-
|
|
183
|
+
Each algorithm exports size constants:
|
|
123
184
|
|
|
124
185
|
```typescript
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// Combined (nonce || ciphertext || tag)
|
|
130
|
-
aegis128LEncrypt(msg, ad, key, nonce?, tagLen?): Uint8Array
|
|
131
|
-
aegis128LDecrypt(sealed, ad, key, tagLen?): Uint8Array | null
|
|
132
|
-
|
|
133
|
-
// Detached (separate ciphertext and tag)
|
|
134
|
-
aegis128LEncryptDetached(msg, ad, key, nonce, tagLen?): { ciphertext, tag }
|
|
135
|
-
aegis128LDecryptDetached(ciphertext, tag, ad, key, nonce): Uint8Array | null
|
|
136
|
-
|
|
137
|
-
// MAC (nonce is optional, defaults to zero)
|
|
138
|
-
aegis128LMac(data, key, nonce?, tagLen?): Uint8Array
|
|
139
|
-
aegis128LMacVerify(data, tag, key, nonce?): boolean
|
|
140
|
-
|
|
141
|
-
// Constants
|
|
142
|
-
AEGIS_128L_KEY_SIZE // 16
|
|
143
|
-
AEGIS_128L_NONCE_SIZE // 16
|
|
186
|
+
import { AEGIS_128L_KEY_SIZE, AEGIS_128L_NONCE_SIZE } from "aegis-aead";
|
|
187
|
+
// AEGIS_128L_KEY_SIZE = 16
|
|
188
|
+
// AEGIS_128L_NONCE_SIZE = 16
|
|
144
189
|
```
|
|
145
190
|
|
|
146
|
-
### AEGIS-
|
|
147
|
-
|
|
148
|
-
```typescript
|
|
149
|
-
// Key/Nonce generation
|
|
150
|
-
aegis256CreateKey(): Uint8Array // 32 random bytes
|
|
151
|
-
aegis256CreateNonce(): Uint8Array // 32 random bytes
|
|
191
|
+
### Parallel Variants (AEGIS-128X / AEGIS-256X)
|
|
152
192
|
|
|
153
|
-
|
|
154
|
-
aegis256Encrypt(msg, ad, key, nonce?, tagLen?): Uint8Array
|
|
155
|
-
aegis256Decrypt(sealed, ad, key, tagLen?): Uint8Array | null
|
|
193
|
+
The X variants support a configurable degree of parallelism:
|
|
156
194
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
// MAC (nonce is optional, defaults to zero)
|
|
162
|
-
aegis256Mac(data, key, nonce?, tagLen?): Uint8Array
|
|
163
|
-
aegis256MacVerify(data, tag, key, nonce?): boolean
|
|
195
|
+
```typescript
|
|
196
|
+
// Pre-configured for degree 2 and 4
|
|
197
|
+
import { aegis128X2Encrypt, aegis128X4Encrypt } from "aegis-aead";
|
|
164
198
|
|
|
165
|
-
//
|
|
166
|
-
|
|
167
|
-
|
|
199
|
+
// Or use custom degree (typically 2 or 4)
|
|
200
|
+
import { aegis128XEncrypt } from "aegis-aead";
|
|
201
|
+
const sealed = aegis128XEncrypt(msg, ad, key, nonce, 16, 4); // degree=4
|
|
168
202
|
```
|
|
169
203
|
|
|
170
|
-
|
|
204
|
+
## Security Considerations
|
|
171
205
|
|
|
172
|
-
|
|
206
|
+
### Nonce Safety
|
|
173
207
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
aegis128X2CreateKey(): Uint8Array // alias
|
|
179
|
-
aegis128X2CreateNonce(): Uint8Array
|
|
180
|
-
aegis128X4CreateKey(): Uint8Array // alias
|
|
181
|
-
aegis128X4CreateNonce(): Uint8Array
|
|
182
|
-
|
|
183
|
-
// Combined (nonce || ciphertext || tag)
|
|
184
|
-
aegis128X2Encrypt(msg, ad, key, nonce?, tagLen?): Uint8Array
|
|
185
|
-
aegis128X2Decrypt(sealed, ad, key, tagLen?): Uint8Array | null
|
|
186
|
-
aegis128X4Encrypt(msg, ad, key, nonce?, tagLen?): Uint8Array
|
|
187
|
-
aegis128X4Decrypt(sealed, ad, key, tagLen?): Uint8Array | null
|
|
188
|
-
|
|
189
|
-
// Detached (separate ciphertext and tag)
|
|
190
|
-
aegis128X2EncryptDetached(msg, ad, key, nonce, tagLen?): { ciphertext, tag }
|
|
191
|
-
aegis128X2DecryptDetached(ciphertext, tag, ad, key, nonce): Uint8Array | null
|
|
192
|
-
aegis128X4EncryptDetached(msg, ad, key, nonce, tagLen?): { ciphertext, tag }
|
|
193
|
-
aegis128X4DecryptDetached(ciphertext, tag, ad, key, nonce): Uint8Array | null
|
|
194
|
-
|
|
195
|
-
// MAC (nonce is optional, defaults to zero)
|
|
196
|
-
aegis128X2Mac(data, key, nonce?, tagLen?): Uint8Array
|
|
197
|
-
aegis128X2MacVerify(data, tag, key, nonce?): boolean
|
|
198
|
-
aegis128X4Mac(data, key, nonce?, tagLen?): Uint8Array
|
|
199
|
-
aegis128X4MacVerify(data, tag, key, nonce?): boolean
|
|
200
|
-
|
|
201
|
-
// Custom degree
|
|
202
|
-
aegis128XEncrypt(msg, ad, key, nonce?, tagLen?, degree?): Uint8Array
|
|
203
|
-
aegis128XDecrypt(sealed, ad, key, tagLen?, degree?): Uint8Array | null
|
|
204
|
-
aegis128XEncryptDetached(msg, ad, key, nonce, tagLen?, degree?): { ciphertext, tag }
|
|
205
|
-
aegis128XDecryptDetached(ciphertext, tag, ad, key, nonce, degree?): Uint8Array | null
|
|
206
|
-
aegis128XMac(data, key, nonce?, tagLen?, degree?): Uint8Array
|
|
207
|
-
aegis128XMacVerify(data, tag, key, nonce?, degree?): boolean
|
|
208
|
-
|
|
209
|
-
// Constants
|
|
210
|
-
AEGIS_128X_KEY_SIZE // 16
|
|
211
|
-
AEGIS_128X_NONCE_SIZE // 16
|
|
212
|
-
```
|
|
208
|
+
- Combined mode generates random nonces automatically
|
|
209
|
+
- Detached mode requires you to provide nonces - never reuse a nonce with the same key
|
|
210
|
+
- AEGIS-128L/128X: Safe for up to 2^48 messages per key with random nonces
|
|
211
|
+
- AEGIS-256/256X: No practical limits on message count
|
|
213
212
|
|
|
214
|
-
###
|
|
213
|
+
### Tag Lengths
|
|
215
214
|
|
|
216
|
-
|
|
215
|
+
All algorithms support 16-byte (128-bit) and 32-byte (256-bit) tags:
|
|
217
216
|
|
|
218
217
|
```typescript
|
|
219
|
-
//
|
|
220
|
-
|
|
221
|
-
aegis256XCreateNonce(): Uint8Array // 32 random bytes
|
|
222
|
-
aegis256X2CreateKey(): Uint8Array // alias
|
|
223
|
-
aegis256X2CreateNonce(): Uint8Array
|
|
224
|
-
aegis256X4CreateKey(): Uint8Array // alias
|
|
225
|
-
aegis256X4CreateNonce(): Uint8Array
|
|
226
|
-
|
|
227
|
-
// Combined (nonce || ciphertext || tag)
|
|
228
|
-
aegis256X2Encrypt(msg, ad, key, nonce?, tagLen?): Uint8Array
|
|
229
|
-
aegis256X2Decrypt(sealed, ad, key, tagLen?): Uint8Array | null
|
|
230
|
-
aegis256X4Encrypt(msg, ad, key, nonce?, tagLen?): Uint8Array
|
|
231
|
-
aegis256X4Decrypt(sealed, ad, key, tagLen?): Uint8Array | null
|
|
232
|
-
|
|
233
|
-
// Detached (separate ciphertext and tag)
|
|
234
|
-
aegis256X2EncryptDetached(msg, ad, key, nonce, tagLen?): { ciphertext, tag }
|
|
235
|
-
aegis256X2DecryptDetached(ciphertext, tag, ad, key, nonce): Uint8Array | null
|
|
236
|
-
aegis256X4EncryptDetached(msg, ad, key, nonce, tagLen?): { ciphertext, tag }
|
|
237
|
-
aegis256X4DecryptDetached(ciphertext, tag, ad, key, nonce): Uint8Array | null
|
|
238
|
-
|
|
239
|
-
// MAC (nonce is optional, defaults to zero)
|
|
240
|
-
aegis256X2Mac(data, key, nonce?, tagLen?): Uint8Array
|
|
241
|
-
aegis256X2MacVerify(data, tag, key, nonce?): boolean
|
|
242
|
-
aegis256X4Mac(data, key, nonce?, tagLen?): Uint8Array
|
|
243
|
-
aegis256X4MacVerify(data, tag, key, nonce?): boolean
|
|
244
|
-
|
|
245
|
-
// Custom degree
|
|
246
|
-
aegis256XEncrypt(msg, ad, key, nonce?, tagLen?, degree?): Uint8Array
|
|
247
|
-
aegis256XDecrypt(sealed, ad, key, tagLen?, degree?): Uint8Array | null
|
|
248
|
-
aegis256XEncryptDetached(msg, ad, key, nonce, tagLen?, degree?): { ciphertext, tag }
|
|
249
|
-
aegis256XDecryptDetached(ciphertext, tag, ad, key, nonce, degree?): Uint8Array | null
|
|
250
|
-
aegis256XMac(data, key, nonce?, tagLen?, degree?): Uint8Array
|
|
251
|
-
aegis256XMacVerify(data, tag, key, nonce?, degree?): boolean
|
|
252
|
-
|
|
253
|
-
// Constants
|
|
254
|
-
AEGIS_256X_KEY_SIZE // 32
|
|
255
|
-
AEGIS_256X_NONCE_SIZE // 32
|
|
218
|
+
// 32-byte tag
|
|
219
|
+
const sealed = aegis128LEncrypt(msg, ad, key, undefined, 32);
|
|
256
220
|
```
|
|
257
221
|
|
|
258
|
-
###
|
|
259
|
-
|
|
260
|
-
```typescript
|
|
261
|
-
// Key/Nonce generation
|
|
262
|
-
aegis128LBsCreateKey(): Uint8Array // 16 random bytes
|
|
263
|
-
aegis128LBsCreateNonce(): Uint8Array // 16 random bytes
|
|
222
|
+
### Bitsliced Variants
|
|
264
223
|
|
|
265
|
-
|
|
266
|
-
aegis128LBsEncrypt(msg, ad, key, nonce?, tagLen?): Uint8Array
|
|
267
|
-
aegis128LBsDecrypt(sealed, ad, key, tagLen?): Uint8Array | null
|
|
224
|
+
The `-BS` variants use a constant-time bitsliced AES implementation that doesn't use lookup tables. This prevents cache-timing attacks at the cost of ~20% performance.
|
|
268
225
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
226
|
+
Use bitsliced variants when:
|
|
227
|
+
- Running on shared infrastructure (cloud VMs, containers)
|
|
228
|
+
- Attackers may observe timing information
|
|
229
|
+
- Processing attacker-controlled data with secret keys
|
|
272
230
|
|
|
273
|
-
|
|
274
|
-
aegis128LBsMac(data, key, nonce?, tagLen?): Uint8Array
|
|
275
|
-
aegis128LBsMacVerify(data, tag, key, nonce?): boolean
|
|
231
|
+
For most applications, standard variants are safe since AEGIS's continuous state mixing makes timing attacks impractical.
|
|
276
232
|
|
|
277
|
-
|
|
278
|
-
AEGIS_128L_BS_KEY_SIZE // 16
|
|
279
|
-
AEGIS_128L_BS_NONCE_SIZE // 16
|
|
280
|
-
```
|
|
233
|
+
## Compatibility
|
|
281
234
|
|
|
282
|
-
|
|
235
|
+
Runtime Requirements:
|
|
283
236
|
|
|
284
|
-
|
|
285
|
-
// Key/Nonce generation
|
|
286
|
-
aegis256BsCreateKey(): Uint8Array // 32 random bytes
|
|
287
|
-
aegis256BsCreateNonce(): Uint8Array // 32 random bytes
|
|
237
|
+
The library uses the Web Crypto API (`crypto.getRandomValues`) for key/nonce generation:
|
|
288
238
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
239
|
+
- All modern browsers
|
|
240
|
+
- Node.js 18+
|
|
241
|
+
- Deno
|
|
242
|
+
- Bun
|
|
292
243
|
|
|
293
|
-
|
|
294
|
-
aegis256BsEncryptDetached(msg, ad, key, nonce, tagLen?): { ciphertext, tag }
|
|
295
|
-
aegis256BsDecryptDetached(ciphertext, tag, ad, key, nonce): Uint8Array | null
|
|
244
|
+
Interoperability:
|
|
296
245
|
|
|
297
|
-
|
|
298
|
-
aegis256BsMac(data, key, nonce?, tagLen?): Uint8Array
|
|
299
|
-
aegis256BsMacVerify(data, tag, key, nonce?): boolean
|
|
300
|
-
|
|
301
|
-
// Constants
|
|
302
|
-
AEGIS_256_BS_KEY_SIZE // 32
|
|
303
|
-
AEGIS_256_BS_NONCE_SIZE // 32
|
|
304
|
-
```
|
|
246
|
+
This library implements the [AEGIS IETF draft specification](https://datatracker.ietf.org/doc/draft-irtf-cfrg-aegis-aead/) and interoperates with any compliant implementation. See the [full list of AEGIS implementations](https://github.com/cfrg/draft-irtf-cfrg-aegis-aead?tab=readme-ov-file#known-implementations).
|
|
305
247
|
|
|
306
248
|
## Browser Example
|
|
307
249
|
|
|
308
|
-
A browser
|
|
250
|
+
A browser demo is included:
|
|
309
251
|
|
|
310
252
|
```bash
|
|
311
253
|
bun run build:example
|
|
312
254
|
open examples/index.html
|
|
313
255
|
```
|
|
314
|
-
|
|
315
|
-
The example demonstrates encryption/decryption with a simple UI where you can enter a message, encrypt it, and decrypt it back.
|
|
316
|
-
|
|
317
|
-
## Compatibility
|
|
318
|
-
|
|
319
|
-
The key/nonce generation functions use the Web Crypto API (`globalThis.crypto.getRandomValues`) which is available in:
|
|
320
|
-
|
|
321
|
-
- All modern browsers
|
|
322
|
-
- Node.js 18+
|
|
323
|
-
- Deno
|
|
324
|
-
- Bun
|
|
325
|
-
|
|
326
|
-
## Interoperability
|
|
327
|
-
|
|
328
|
-
This library follows the [AEGIS IETF draft specification](https://datatracker.ietf.org/doc/draft-irtf-cfrg-aegis-aead/) and can exchange encrypted messages with any compliant implementation, including native libraries in C, Rust, Go, Zig, and more.
|
|
329
|
-
|
|
330
|
-
See the [full list of AEGIS implementations](https://github.com/cfrg/draft-irtf-cfrg-aegis-aead?tab=readme-ov-file#known-implementations).
|
package/dist/aegis128l-bs.d.ts
CHANGED
|
@@ -70,6 +70,16 @@ export declare class Aegis128LBsState {
|
|
|
70
70
|
* @returns 32-byte plaintext block
|
|
71
71
|
*/
|
|
72
72
|
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
|
+
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
|
+
decInPlace(block: Uint8Array): void;
|
|
73
83
|
/**
|
|
74
84
|
* Decrypts a partial (final) ciphertext block smaller than 32 bytes.
|
|
75
85
|
* @param cn - Partial ciphertext block (1-31 bytes)
|
|
@@ -108,6 +118,28 @@ export declare function aegis128LBsEncryptDetached(msg: Uint8Array, ad: Uint8Arr
|
|
|
108
118
|
* @returns Decrypted plaintext, or null if authentication fails
|
|
109
119
|
*/
|
|
110
120
|
export declare function aegis128LBsDecryptDetached(ct: Uint8Array, tag: Uint8Array, ad: Uint8Array, key: Uint8Array, nonce: Uint8Array): Uint8Array | null;
|
|
121
|
+
/**
|
|
122
|
+
* 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
|
+
*/
|
|
131
|
+
export declare function aegis128LBsEncryptDetachedInPlace(data: Uint8Array, ad: Uint8Array, key: Uint8Array, nonce: Uint8Array, tagLen?: 16 | 32): Uint8Array;
|
|
132
|
+
/**
|
|
133
|
+
* 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
|
+
*/
|
|
142
|
+
export declare function aegis128LBsDecryptDetachedInPlace(data: Uint8Array, tag: Uint8Array, ad: Uint8Array, key: Uint8Array, nonce: Uint8Array): boolean;
|
|
111
143
|
export declare const AEGIS_128L_BS_NONCE_SIZE = 16;
|
|
112
144
|
export declare const AEGIS_128L_BS_KEY_SIZE = 16;
|
|
113
145
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aegis128l-bs.d.ts","sourceRoot":"","sources":["../src/aegis128l-bs.ts"],"names":[],"mappings":"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"}
|
|
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
|
@@ -215,6 +215,20 @@ export class Aegis128LBsState {
|
|
|
215
215
|
this.decTo(ci, out);
|
|
216
216
|
return out;
|
|
217
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Encrypts a 32-byte plaintext block in-place.
|
|
220
|
+
* @param block - 32-byte buffer (plaintext in, ciphertext out)
|
|
221
|
+
*/
|
|
222
|
+
encInPlace(block) {
|
|
223
|
+
this.encTo(block, block);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Decrypts a 32-byte ciphertext block in-place.
|
|
227
|
+
* @param block - 32-byte buffer (ciphertext in, plaintext out)
|
|
228
|
+
*/
|
|
229
|
+
decInPlace(block) {
|
|
230
|
+
this.decTo(block, block);
|
|
231
|
+
}
|
|
218
232
|
/**
|
|
219
233
|
* Decrypts a partial (final) ciphertext block smaller than 32 bytes.
|
|
220
234
|
* @param cn - Partial ciphertext block (1-31 bytes)
|
|
@@ -383,6 +397,71 @@ export function aegis128LBsDecryptDetached(ct, tag, ad, key, nonce) {
|
|
|
383
397
|
}
|
|
384
398
|
return msg;
|
|
385
399
|
}
|
|
400
|
+
/**
|
|
401
|
+
* 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
|
+
*/
|
|
410
|
+
export function aegis128LBsEncryptDetachedInPlace(data, ad, key, nonce, tagLen = 16) {
|
|
411
|
+
const state = new Aegis128LBsState();
|
|
412
|
+
state.init(key, nonce);
|
|
413
|
+
const adPadded = zeroPad(ad, RATE);
|
|
414
|
+
for (let i = 0; i + RATE <= adPadded.length; i += RATE) {
|
|
415
|
+
state.absorb(adPadded.subarray(i, i + RATE));
|
|
416
|
+
}
|
|
417
|
+
const msgLen = data.length;
|
|
418
|
+
const fullBlocksLen = Math.floor(msgLen / RATE) * RATE;
|
|
419
|
+
for (let i = 0; i < fullBlocksLen; i += RATE) {
|
|
420
|
+
state.encInPlace(data.subarray(i, i + RATE));
|
|
421
|
+
}
|
|
422
|
+
if (msgLen > fullBlocksLen) {
|
|
423
|
+
const lastPartial = data.subarray(fullBlocksLen);
|
|
424
|
+
const lastBlock = zeroPad(lastPartial, RATE);
|
|
425
|
+
const encBlock = state.enc(lastBlock);
|
|
426
|
+
lastPartial.set(encBlock.subarray(0, lastPartial.length));
|
|
427
|
+
}
|
|
428
|
+
return state.finalize(ad.length, msgLen, tagLen);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* 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
|
+
*/
|
|
440
|
+
export function aegis128LBsDecryptDetachedInPlace(data, tag, ad, key, nonce) {
|
|
441
|
+
const tagLen = tag.length;
|
|
442
|
+
const state = new Aegis128LBsState();
|
|
443
|
+
state.init(key, nonce);
|
|
444
|
+
const adPadded = zeroPad(ad, RATE);
|
|
445
|
+
for (let i = 0; i + RATE <= adPadded.length; i += RATE) {
|
|
446
|
+
state.absorb(adPadded.subarray(i, i + RATE));
|
|
447
|
+
}
|
|
448
|
+
const msgLen = data.length;
|
|
449
|
+
const fullBlocksLen = Math.floor(msgLen / RATE) * RATE;
|
|
450
|
+
for (let i = 0; i < fullBlocksLen; i += RATE) {
|
|
451
|
+
state.decInPlace(data.subarray(i, i + RATE));
|
|
452
|
+
}
|
|
453
|
+
if (msgLen > fullBlocksLen) {
|
|
454
|
+
const lastPartial = data.subarray(fullBlocksLen);
|
|
455
|
+
const decrypted = state.decPartial(lastPartial);
|
|
456
|
+
lastPartial.set(decrypted);
|
|
457
|
+
}
|
|
458
|
+
const expectedTag = state.finalize(ad.length, msgLen, tagLen);
|
|
459
|
+
if (!constantTimeEqual(tag, expectedTag)) {
|
|
460
|
+
data.fill(0);
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
386
465
|
export const AEGIS_128L_BS_NONCE_SIZE = 16;
|
|
387
466
|
export const AEGIS_128L_BS_KEY_SIZE = 16;
|
|
388
467
|
/**
|