@immahq/aegis 0.1.2 → 0.1.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 CHANGED
@@ -16,10 +16,11 @@
16
16
  - **Identity Management**: Create identities with specific userIds for better user correlation and management.
17
17
  - **Key Rotation**: Supports identity rotation with option to maintain same userId or assign new ones.
18
18
  - **Replay Protection**: Built-in protection against message replay attacks.
19
- - **Minimal Dependencies**: Relies on robust, well-audited libraries like `@noble/curves` and `@noble/hashes`.
20
19
 
21
20
  ---
22
21
 
22
+
23
+
23
24
  ## **Installation**
24
25
 
25
26
  Install the library using npm, yarn, or pnpm.
@@ -35,7 +36,10 @@ For React Native, you may need a
35
36
 
36
37
  ---
37
38
 
38
- ## **Quick Start**
39
+ ## **Setup**
40
+
41
+ **Quick start**: Check [examples](/examples) for samples with browser, React Native, Electron, and Tauri
42
+
39
43
 
40
44
  ### **1. Implement a Storage Adapter**
41
45
 
@@ -217,8 +221,6 @@ console.log(new TextDecoder().decode(groupPlaintext)); // "Dinner at 8 PM!"
217
221
 
218
222
  ## **API Reference**
219
223
 
220
- ### **Core & Configuration**
221
-
222
224
  ### **Identity Management**
223
225
 
224
226
  - **`aegis.createIdentity(userId?: string): Promise<{ identity, publicBundle }>`** - Creates a new identity with optional userId
@@ -250,10 +252,8 @@ console.log(new TextDecoder().decode(groupPlaintext)); // "Dinner at 8 PM!"
250
252
  ## **Testing and Examples**
251
253
 
252
254
  - **Run All Tests**: `npm test`
253
- - **Run Sample Flow**: `npm run sample`
254
- - This executes `examples/usage.ts`, demonstrating a complete flow: identity creation, session handshake, 1:1 messaging, and group setup.
255
- - **Run Benchmarks**: `npm run benchmark`
256
- - Executes performance benchmarks for various operations including identity creation, session establishment, message encryption/decryption, and group operations.
255
+ - **Run peer messaging demo**: `npm run demo`
256
+ - **Run group messaging demo**: `npm run demo:group`
257
257
 
258
258
  ---
259
259
 
@@ -279,32 +279,6 @@ Aegis is built on a hybrid model:
279
279
 
280
280
  ---
281
281
 
282
- ## **Performance & Benchmarks**
283
-
284
- Aegis includes comprehensive benchmarking to measure performance across various operations:
285
-
286
- - **Identity Creation**: ~30-50ms per operation
287
- - **Session Establishment**: ~25-50ms per operation
288
- - **Message Encryption/Decryption**: ~30-70ms per round-trip
289
- - **Group Operations**: ~40-130ms depending on group size
290
- - **Ratchet Operations**: ~30-60ms per operation
291
-
292
- Run `npm run benchmark` to see performance metrics on your system.
293
-
294
- ---
295
-
296
- ## **Contributing & Roadmap**
297
-
298
- We welcome contributions. Priority areas include:
299
-
300
- - Enhanced utilities for server-side OTPK lifecycle management.
301
- - Improved examples for cross-platform secure storage.
302
- - Advanced group management features (admin roles, permissions, etc.).
303
- - Performance optimizations for large group messaging.
304
- - Additional storage adapters for popular databases and platforms.
305
-
306
- ---
307
-
308
282
  ## **License**
309
283
 
310
284
  MIT
package/aegis.d.ts CHANGED
@@ -1,6 +1,250 @@
1
+ //Types
1
2
  declare module "@immahq/aegis" {
2
- export class Aegis {}
3
- export interface MemoryStorage extends StorageAdapter {}
3
+ export class Aegis {
4
+ constructor(storage: StorageAdapter);
5
+ createIdentity(userId?: string): Promise<AegisIdentity>;
6
+ getIdentity(): Promise<Identity>;
7
+ rotateIdentity(userId?: string): Promise<AegisIdentity>;
8
+ getPublicBundle(): Promise<PublicBundle>;
9
+ createSession(publicBundle: PublicBundle): Promise<{
10
+ sessionId: string;
11
+ ciphertext: Uint8Array;
12
+ confirmationMac: Uint8Array;
13
+ }>;
14
+ createResponderSession(
15
+ publicBundle: PublicBundle,
16
+ ciphertext: Uint8Array,
17
+ initiatorConfirmationMac?: Uint8Array,
18
+ ): Promise<{
19
+ sessionId: string;
20
+ confirmationMac: Uint8Array;
21
+ isValid: boolean;
22
+ }>;
23
+ confirmSession(
24
+ sessionId: string,
25
+ responderConfirmationMac: Uint8Array,
26
+ ): Promise<boolean>;
27
+ getSessions(): Promise<Session[]>;
28
+ cleanupOldSessions(maxAge?: number): Promise<void>;
29
+ encryptMessage(
30
+ sessionId: string,
31
+ plaintext: string | Uint8Array,
32
+ ): Promise<EncryptedMessage>;
33
+ decryptMessage(
34
+ sessionId: string,
35
+ encrypted: EncryptedMessage,
36
+ ): Promise<{
37
+ plaintext: Uint8Array;
38
+ needsConfirmation?: boolean;
39
+ }>;
40
+ triggerRatchet(sessionId: string): Promise<void>;
41
+ getReplayProtectionStatus(sessionId: string): Promise<{
42
+ storedMessageIds: number;
43
+ lastProcessedTimestamp: number;
44
+ replayWindowSize: number;
45
+ }>;
46
+ getConfirmationMac(sessionId: string): Promise<Uint8Array | null>;
47
+ getStorage(): StorageAdapter;
48
+ createGroup(
49
+ name: string,
50
+ members: string[],
51
+ memberKemPublicKeys: Map<string, Uint8Array>,
52
+ memberDsaPublicKeys: Map<string, Uint8Array>,
53
+ ): Promise<Group>;
54
+ addGroupMember(
55
+ groupId: string,
56
+ userId: string,
57
+ session: Session,
58
+ userPublicKey: Uint8Array,
59
+ ): Promise<void>;
60
+ removeGroupMember(groupId: string, userId: string): Promise<void>;
61
+ updateGroupKey(groupId: string): Promise<void>;
62
+ encryptGroupMessage(
63
+ groupId: string,
64
+ message: string | Uint8Array,
65
+ ): Promise<GroupMessage>;
66
+ decryptGroupMessage(
67
+ groupId: string,
68
+ encrypted: GroupMessage,
69
+ ): Promise<Uint8Array>;
70
+ getGroup(groupId: string): Promise<Group | null>;
71
+ getGroups(): Promise<Group[]>;
72
+ }
73
+
74
+ export class MemoryStorage implements StorageAdapter {
75
+ saveIdentity(identity: Identity): Promise<void>;
76
+ getIdentity(): Promise<Identity | null>;
77
+ deleteIdentity(): Promise<void>;
78
+ saveSession(sessionId: string, session: Session): Promise<void>;
79
+ getSession(sessionId: string): Promise<Session | null>;
80
+ deleteSession(sessionId: string): Promise<void>;
81
+ listSessions(): Promise<string[]>;
82
+ deleteAllSessions(): Promise<void>;
83
+ }
84
+
85
+ export class Logger {
86
+ static log(
87
+ component: string,
88
+ message: string,
89
+ data?: Record<string, any>,
90
+ ): void;
91
+ static error(component: string, message: string, error?: any): void;
92
+ static warn(
93
+ component: string,
94
+ message: string,
95
+ data?: Record<string, any>,
96
+ ): void;
97
+ }
98
+
99
+ export class KemRatchet {}
100
+
101
+ export class SessionKeyExchange {
102
+ static createInitiatorSession(
103
+ identity: Identity,
104
+ peerBundle: PublicBundle,
105
+ ): {
106
+ sessionId: string;
107
+ rootKey: Uint8Array;
108
+ sendingChainKey: Uint8Array;
109
+ receivingChainKey: Uint8Array;
110
+ ciphertext: Uint8Array;
111
+ confirmationMac: Uint8Array;
112
+ };
113
+ static createResponderSession(
114
+ identity: Identity,
115
+ peerBundle: PublicBundle,
116
+ ciphertext: Uint8Array,
117
+ initiatorConfirmationMac?: Uint8Array,
118
+ ): {
119
+ sessionId: string;
120
+ rootKey: Uint8Array;
121
+ sendingChainKey: Uint8Array;
122
+ receivingChainKey: Uint8Array;
123
+ confirmationMac: Uint8Array;
124
+ isValid: boolean;
125
+ };
126
+ static verifyKeyConfirmation(
127
+ sessionId: string,
128
+ rootKey: Uint8Array,
129
+ receivingChainKey: Uint8Array,
130
+ confirmationMac: Uint8Array,
131
+ ): boolean;
132
+ }
133
+
134
+ export class IdentityManager {
135
+ constructor(storage: StorageAdapter);
136
+ createIdentity(userId?: string): Promise<AegisIdentity>;
137
+ getIdentity(): Promise<Identity>;
138
+ getPublicBundle(): Promise<PublicBundle>;
139
+ rotateIdentity(userId?: string): Promise<AegisIdentity>;
140
+ }
141
+
142
+ export class SessionManager {
143
+ constructor(storage: StorageAdapter);
144
+ createSession(
145
+ identity: Identity,
146
+ peerBundle: PublicBundle,
147
+ ): Promise<{
148
+ sessionId: string;
149
+ ciphertext: Uint8Array;
150
+ confirmationMac: Uint8Array;
151
+ }>;
152
+ createResponderSession(
153
+ identity: Identity,
154
+ peerBundle: PublicBundle,
155
+ ciphertext: Uint8Array,
156
+ initiatorConfirmationMac?: Uint8Array,
157
+ ): Promise<{
158
+ sessionId: string;
159
+ confirmationMac: Uint8Array;
160
+ isValid: boolean;
161
+ }>;
162
+ confirmSession(
163
+ sessionId: string,
164
+ responderConfirmationMac: Uint8Array,
165
+ ): Promise<boolean>;
166
+ getSessions(): Promise<Session[]>;
167
+ cleanupOldSessions(maxAge?: number): Promise<void>;
168
+ }
169
+
170
+ export class CryptoManager {
171
+ constructor(storage: StorageAdapter);
172
+ }
173
+
174
+ export class RatchetManager {
175
+ shouldPerformSendingRatchet(session: Session): boolean;
176
+ performSendingRatchet(session: Session): Session;
177
+ needsReceivingRatchet(session: Session, header: any): boolean;
178
+ performReceivingRatchet(
179
+ session: Session,
180
+ kemCiphertext: Uint8Array,
181
+ ): Session;
182
+ applyPendingRatchet(session: Session): Session;
183
+ getDecryptionChainForRatchetMessage(session: Session): RatchetChain | null;
184
+ triggerRatchet(sessionId: string, session: Session): Promise<Session>;
185
+ }
186
+
187
+ export class ReplayProtection {
188
+ getSkippedKeyId(
189
+ ratchetPublicKey: Uint8Array,
190
+ messageNumber: number,
191
+ ): string;
192
+ storeReceivedMessageId(session: Session, messageId: string): void;
193
+ cleanupSkippedKeys(session: Session): void;
194
+ getReplayProtectionStatus(
195
+ sessionId: string,
196
+ session: Session,
197
+ ): Promise<{
198
+ storedMessageIds: number;
199
+ lastProcessedTimestamp: number;
200
+ replayWindowSize: number;
201
+ }>;
202
+ }
203
+
204
+ export class GroupManager {
205
+ constructor(storage: StorageAdapter);
206
+ initialize(identity: Identity): Promise<void>;
207
+ createGroup(
208
+ name: string,
209
+ members: string[],
210
+ memberKemPublicKeys: Map<string, Uint8Array>,
211
+ memberDsaPublicKeys: Map<string, Uint8Array>,
212
+ ): Promise<Group>;
213
+ addMember(
214
+ groupId: string,
215
+ userId: string,
216
+ session: Session,
217
+ userPublicKey: Uint8Array,
218
+ ): Promise<void>;
219
+ removeMember(groupId: string, userId: string): Promise<void>;
220
+ updateGroupKey(groupId: string): Promise<void>;
221
+ encryptMessage(
222
+ groupId: string,
223
+ message: string | Uint8Array,
224
+ ): Promise<GroupMessage>;
225
+ decryptMessage(
226
+ groupId: string,
227
+ encrypted: GroupMessage,
228
+ ): Promise<Uint8Array>;
229
+ getGroup(groupId: string): Promise<Group | null>;
230
+ getGroups(): Promise<Group[]>;
231
+ }
232
+
233
+ export interface AegisIdentity {
234
+ identity: Identity;
235
+ publicBundle: PublicBundle;
236
+ }
237
+
238
+ export interface StorageAdapter {
239
+ saveIdentity(identity: Identity): Promise<void>;
240
+ getIdentity(): Promise<Identity | null>;
241
+ deleteIdentity(): Promise<void>;
242
+ saveSession(sessionId: string, session: Session): Promise<void>;
243
+ getSession(sessionId: string): Promise<Session | null>;
244
+ deleteSession(sessionId: string): Promise<void>;
245
+ listSessions(): Promise<string[]>;
246
+ deleteAllSessions(): Promise<void>;
247
+ }
4
248
 
5
249
  export interface Identity {
6
250
  kemKeyPair: { publicKey: Uint8Array; secretKey: Uint8Array };
@@ -109,17 +353,6 @@ declare module "@immahq/aegis" {
109
353
  createdAt: number;
110
354
  }
111
355
 
112
- export interface StorageAdapter {
113
- saveIdentity(identity: Identity): Promise<void>;
114
- getIdentity(): Promise<Identity | null>;
115
- deleteIdentity(): Promise<void>;
116
- saveSession(sessionId: string, session: Session): Promise<void>;
117
- getSession(sessionId: string): Promise<Session | null>;
118
- deleteSession(sessionId: string): Promise<void>;
119
- listSessions(): Promise<string[]>;
120
- deleteAllSessions(): Promise<void>;
121
- }
122
-
123
356
  export interface KeyConfirmationData {
124
357
  sessionId: string;
125
358
  mac: Uint8Array;
@@ -169,31 +402,4 @@ declare module "@immahq/aegis" {
169
402
  canManageMembers: boolean;
170
403
  canUpdateGroup: boolean;
171
404
  }
172
-
173
- export interface GroupManager {
174
- createGroup(
175
- name: string,
176
- members: string[],
177
- memberKemPublicKeys: Map<string, Uint8Array>,
178
- memberDsaPublicKeys: Map<string, Uint8Array>,
179
- ): Promise<Group>;
180
- addMember(
181
- groupId: string,
182
- userId: string,
183
- session: Session,
184
- userPublicKey: Uint8Array,
185
- ): Promise<void>;
186
- removeMember(groupId: string, userId: string): Promise<void>;
187
- updateGroupKey(groupId: string): Promise<void>;
188
- encryptMessage(
189
- groupId: string,
190
- message: string | Uint8Array,
191
- ): Promise<GroupMessage>;
192
- decryptMessage(
193
- groupId: string,
194
- encrypted: GroupMessage,
195
- ): Promise<Uint8Array>;
196
- getGroup(groupId: string): Promise<Group | null>;
197
- getGroups(): Promise<Group[]>;
198
- }
199
405
  }
package/dist/storage.js CHANGED
@@ -1,3 +1,4 @@
1
+ //Default storage adapter for the SDK. Stores data in memory.
1
2
  export class MemoryStorage {
2
3
  constructor() {
3
4
  Object.defineProperty(this, "identity", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immahq/aegis",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Lightweight, storage-agnostic library for client-side End-to-End (E2E) encryption",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -33,6 +33,7 @@
33
33
  "cryptography",
34
34
  "encryption",
35
35
  "e2e",
36
+ "e2ee",
36
37
  "end-to-end",
37
38
  "pqc",
38
39
  "post-quantum",
@@ -52,7 +53,6 @@
52
53
  "buffer": "^6.0.3"
53
54
  },
54
55
  "devDependencies": {
55
- "@types/node": "^25.0.3",
56
56
  "rimraf": "^6.1.2",
57
57
  "tsx": "^4.21.0",
58
58
  "typescript": "^5.9.3",