@meshwhisper/sdk 0.1.0
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 +138 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +19 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/chaff/index.d.ts +91 -0
- package/dist/chaff/index.d.ts.map +1 -0
- package/dist/chaff/index.js +268 -0
- package/dist/chaff/index.js.map +1 -0
- package/dist/cluster/index.d.ts +159 -0
- package/dist/cluster/index.d.ts.map +1 -0
- package/dist/cluster/index.js +393 -0
- package/dist/cluster/index.js.map +1 -0
- package/dist/compliance/index.d.ts +129 -0
- package/dist/compliance/index.d.ts.map +1 -0
- package/dist/compliance/index.js +315 -0
- package/dist/compliance/index.js.map +1 -0
- package/dist/crypto/index.d.ts +65 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.js +146 -0
- package/dist/crypto/index.js.map +1 -0
- package/dist/group/index.d.ts +155 -0
- package/dist/group/index.d.ts.map +1 -0
- package/dist/group/index.js +560 -0
- package/dist/group/index.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/namespace/index.d.ts +155 -0
- package/dist/namespace/index.d.ts.map +1 -0
- package/dist/namespace/index.js +278 -0
- package/dist/namespace/index.js.map +1 -0
- package/dist/node/index.d.ts +4 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +19 -0
- package/dist/node/index.js.map +1 -0
- package/dist/packet/index.d.ts +63 -0
- package/dist/packet/index.d.ts.map +1 -0
- package/dist/packet/index.js +244 -0
- package/dist/packet/index.js.map +1 -0
- package/dist/permissions/index.d.ts +107 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +282 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/persistence/idb-storage.d.ts +27 -0
- package/dist/persistence/idb-storage.d.ts.map +1 -0
- package/dist/persistence/idb-storage.js +75 -0
- package/dist/persistence/idb-storage.js.map +1 -0
- package/dist/persistence/index.d.ts +4 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +3 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/node-storage.d.ts +33 -0
- package/dist/persistence/node-storage.d.ts.map +1 -0
- package/dist/persistence/node-storage.js +90 -0
- package/dist/persistence/node-storage.js.map +1 -0
- package/dist/persistence/serialization.d.ts +4 -0
- package/dist/persistence/serialization.d.ts.map +1 -0
- package/dist/persistence/serialization.js +49 -0
- package/dist/persistence/serialization.js.map +1 -0
- package/dist/persistence/types.d.ts +29 -0
- package/dist/persistence/types.d.ts.map +1 -0
- package/dist/persistence/types.js +5 -0
- package/dist/persistence/types.js.map +1 -0
- package/dist/ratchet/index.d.ts +80 -0
- package/dist/ratchet/index.d.ts.map +1 -0
- package/dist/ratchet/index.js +259 -0
- package/dist/ratchet/index.js.map +1 -0
- package/dist/reciprocity/index.d.ts +109 -0
- package/dist/reciprocity/index.d.ts.map +1 -0
- package/dist/reciprocity/index.js +311 -0
- package/dist/reciprocity/index.js.map +1 -0
- package/dist/relay/index.d.ts +87 -0
- package/dist/relay/index.d.ts.map +1 -0
- package/dist/relay/index.js +286 -0
- package/dist/relay/index.js.map +1 -0
- package/dist/routing/index.d.ts +136 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +478 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/sdk/index.d.ts +322 -0
- package/dist/sdk/index.d.ts.map +1 -0
- package/dist/sdk/index.js +1530 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sybil/index.d.ts +123 -0
- package/dist/sybil/index.d.ts.map +1 -0
- package/dist/sybil/index.js +491 -0
- package/dist/sybil/index.js.map +1 -0
- package/dist/transport/browser/index.d.ts +34 -0
- package/dist/transport/browser/index.d.ts.map +1 -0
- package/dist/transport/browser/index.js +176 -0
- package/dist/transport/browser/index.js.map +1 -0
- package/dist/transport/local/index.d.ts +57 -0
- package/dist/transport/local/index.d.ts.map +1 -0
- package/dist/transport/local/index.js +442 -0
- package/dist/transport/local/index.js.map +1 -0
- package/dist/transport/negotiator/index.d.ts +79 -0
- package/dist/transport/negotiator/index.d.ts.map +1 -0
- package/dist/transport/negotiator/index.js +289 -0
- package/dist/transport/negotiator/index.js.map +1 -0
- package/dist/transport/node/index.d.ts +56 -0
- package/dist/transport/node/index.d.ts.map +1 -0
- package/dist/transport/node/index.js +209 -0
- package/dist/transport/node/index.js.map +1 -0
- package/dist/transport/noop/index.d.ts +11 -0
- package/dist/transport/noop/index.d.ts.map +1 -0
- package/dist/transport/noop/index.js +20 -0
- package/dist/transport/noop/index.js.map +1 -0
- package/dist/transport/p2p/index.d.ts +109 -0
- package/dist/transport/p2p/index.d.ts.map +1 -0
- package/dist/transport/p2p/index.js +237 -0
- package/dist/transport/p2p/index.js.map +1 -0
- package/dist/transport/websocket/index.d.ts +89 -0
- package/dist/transport/websocket/index.d.ts.map +1 -0
- package/dist/transport/websocket/index.js +498 -0
- package/dist/transport/websocket/index.js.map +1 -0
- package/dist/transport/websocket/serialize.d.ts +5 -0
- package/dist/transport/websocket/serialize.d.ts.map +1 -0
- package/dist/transport/websocket/serialize.js +55 -0
- package/dist/transport/websocket/serialize.js.map +1 -0
- package/dist/types.d.ts +215 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/dist/x3dh/index.d.ts +120 -0
- package/dist/x3dh/index.d.ts.map +1 -0
- package/dist/x3dh/index.js +290 -0
- package/dist/x3dh/index.js.map +1 -0
- package/package.json +59 -0
- package/src/browser/index.ts +19 -0
- package/src/chaff/index.ts +340 -0
- package/src/cluster/index.ts +482 -0
- package/src/compliance/index.ts +407 -0
- package/src/crypto/index.ts +193 -0
- package/src/group/index.ts +719 -0
- package/src/index.ts +87 -0
- package/src/lz4js.d.ts +58 -0
- package/src/namespace/index.ts +336 -0
- package/src/node/index.ts +19 -0
- package/src/packet/index.ts +326 -0
- package/src/permissions/index.ts +405 -0
- package/src/persistence/idb-storage.ts +83 -0
- package/src/persistence/index.ts +3 -0
- package/src/persistence/node-storage.ts +96 -0
- package/src/persistence/serialization.ts +75 -0
- package/src/persistence/types.ts +33 -0
- package/src/ratchet/index.ts +363 -0
- package/src/reciprocity/index.ts +371 -0
- package/src/relay/index.ts +382 -0
- package/src/routing/index.ts +577 -0
- package/src/sdk/index.ts +1994 -0
- package/src/sybil/index.ts +661 -0
- package/src/transport/browser/index.ts +201 -0
- package/src/transport/local/index.ts +540 -0
- package/src/transport/negotiator/index.ts +397 -0
- package/src/transport/node/index.ts +234 -0
- package/src/transport/noop/index.ts +22 -0
- package/src/transport/p2p/index.ts +345 -0
- package/src/transport/websocket/index.ts +660 -0
- package/src/transport/websocket/serialize.ts +68 -0
- package/src/types.ts +275 -0
- package/src/x3dh/index.ts +388 -0
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// MeshWhisper SDK — Group Messaging Module
|
|
3
|
+
// Dynamic Relay Trees (§10.1) and Sender Key Management (§10.2)
|
|
4
|
+
// ============================================================
|
|
5
|
+
import { gcm } from '@noble/ciphers/aes';
|
|
6
|
+
import { randomBytes } from '../crypto/index.js';
|
|
7
|
+
// ---- Constants ----
|
|
8
|
+
/** Sender key length in bytes. */
|
|
9
|
+
const SENDER_KEY_LENGTH = 32;
|
|
10
|
+
/** AES-GCM nonce length in bytes (96-bit). */
|
|
11
|
+
const GCM_NONCE_LENGTH = 12;
|
|
12
|
+
/** AES-GCM authentication tag length in bytes. */
|
|
13
|
+
const GCM_TAG_LENGTH = 16;
|
|
14
|
+
/** Group ID length in bytes (128-bit random). */
|
|
15
|
+
const GROUP_ID_LENGTH = 16;
|
|
16
|
+
/** Activity window for relay tree scoring, in milliseconds (5 minutes). */
|
|
17
|
+
const ACTIVITY_WINDOW_MS = 5 * 60 * 1000;
|
|
18
|
+
/** Minimum interval between relay tree rebuilds, in milliseconds. */
|
|
19
|
+
const TREE_REBUILD_INTERVAL_MS = 60 * 1000;
|
|
20
|
+
// ============================================================
|
|
21
|
+
// GroupManager
|
|
22
|
+
// ============================================================
|
|
23
|
+
export class GroupManager {
|
|
24
|
+
localPeerId;
|
|
25
|
+
groups = new Map();
|
|
26
|
+
constructor(localPeerId) {
|
|
27
|
+
this.localPeerId = localPeerId;
|
|
28
|
+
}
|
|
29
|
+
// ---- Group Lifecycle ----
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new group. The local peer is the initial admin and tree root.
|
|
32
|
+
* Generates sender keys for the local peer and all initial members.
|
|
33
|
+
*/
|
|
34
|
+
createGroup(name, members, permissionModel) {
|
|
35
|
+
const groupId = this.generateGroupId();
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
const memberMap = new Map();
|
|
38
|
+
const senderKeys = new Map();
|
|
39
|
+
const keyIterations = new Map();
|
|
40
|
+
const activity = new Map();
|
|
41
|
+
// Add self as admin
|
|
42
|
+
const selfKey = this.generateSenderKey();
|
|
43
|
+
memberMap.set(this.localPeerId, {
|
|
44
|
+
id: this.localPeerId,
|
|
45
|
+
senderKey: selfKey,
|
|
46
|
+
role: 'admin',
|
|
47
|
+
joinedAt: now,
|
|
48
|
+
});
|
|
49
|
+
senderKeys.set(this.localPeerId, selfKey);
|
|
50
|
+
keyIterations.set(this.localPeerId, 0);
|
|
51
|
+
activity.set(this.localPeerId, { timestamps: [], lastActive: now });
|
|
52
|
+
// Add initial members
|
|
53
|
+
for (const peerId of members) {
|
|
54
|
+
if (peerId === this.localPeerId)
|
|
55
|
+
continue;
|
|
56
|
+
const memberKey = this.generateSenderKey();
|
|
57
|
+
memberMap.set(peerId, {
|
|
58
|
+
id: peerId,
|
|
59
|
+
senderKey: memberKey,
|
|
60
|
+
role: 'member',
|
|
61
|
+
joinedAt: now,
|
|
62
|
+
});
|
|
63
|
+
senderKeys.set(peerId, memberKey);
|
|
64
|
+
keyIterations.set(peerId, 0);
|
|
65
|
+
activity.set(peerId, { timestamps: [], lastActive: now });
|
|
66
|
+
}
|
|
67
|
+
const group = {
|
|
68
|
+
id: groupId,
|
|
69
|
+
name,
|
|
70
|
+
members: memberMap,
|
|
71
|
+
treeRoot: this.localPeerId,
|
|
72
|
+
permissionModel,
|
|
73
|
+
createdAt: now,
|
|
74
|
+
};
|
|
75
|
+
this.groups.set(groupId, {
|
|
76
|
+
group,
|
|
77
|
+
senderKeys,
|
|
78
|
+
keyIterations,
|
|
79
|
+
activity,
|
|
80
|
+
relayTree: null,
|
|
81
|
+
lastTreeBuild: 0,
|
|
82
|
+
});
|
|
83
|
+
return group;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Joins an existing group using invite data received via a pairwise channel.
|
|
87
|
+
* Stores all distributed sender keys from the invite.
|
|
88
|
+
*/
|
|
89
|
+
joinGroup(groupId, inviteData) {
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
const memberMap = new Map();
|
|
92
|
+
const senderKeys = new Map();
|
|
93
|
+
const keyIterations = new Map();
|
|
94
|
+
const activity = new Map();
|
|
95
|
+
// Populate members from the invite
|
|
96
|
+
for (const peerId of inviteData.members) {
|
|
97
|
+
const existingKey = inviteData.senderKeys.get(peerId);
|
|
98
|
+
memberMap.set(peerId, {
|
|
99
|
+
id: peerId,
|
|
100
|
+
senderKey: existingKey ?? new Uint8Array(SENDER_KEY_LENGTH),
|
|
101
|
+
role: peerId === inviteData.invitedBy ? 'admin' : 'member',
|
|
102
|
+
joinedAt: now,
|
|
103
|
+
});
|
|
104
|
+
if (existingKey) {
|
|
105
|
+
senderKeys.set(peerId, existingKey);
|
|
106
|
+
}
|
|
107
|
+
keyIterations.set(peerId, 0);
|
|
108
|
+
activity.set(peerId, { timestamps: [], lastActive: now });
|
|
109
|
+
}
|
|
110
|
+
// Add self if not already in the member list
|
|
111
|
+
if (!memberMap.has(this.localPeerId)) {
|
|
112
|
+
const selfKey = this.generateSenderKey();
|
|
113
|
+
memberMap.set(this.localPeerId, {
|
|
114
|
+
id: this.localPeerId,
|
|
115
|
+
senderKey: selfKey,
|
|
116
|
+
role: 'member',
|
|
117
|
+
joinedAt: now,
|
|
118
|
+
});
|
|
119
|
+
senderKeys.set(this.localPeerId, selfKey);
|
|
120
|
+
keyIterations.set(this.localPeerId, 0);
|
|
121
|
+
activity.set(this.localPeerId, { timestamps: [], lastActive: now });
|
|
122
|
+
}
|
|
123
|
+
const group = {
|
|
124
|
+
id: groupId,
|
|
125
|
+
name: inviteData.groupName,
|
|
126
|
+
members: memberMap,
|
|
127
|
+
treeRoot: inviteData.invitedBy,
|
|
128
|
+
permissionModel: 'open',
|
|
129
|
+
createdAt: now,
|
|
130
|
+
};
|
|
131
|
+
this.groups.set(groupId, {
|
|
132
|
+
group,
|
|
133
|
+
senderKeys,
|
|
134
|
+
keyIterations,
|
|
135
|
+
activity,
|
|
136
|
+
relayTree: null,
|
|
137
|
+
lastTreeBuild: 0,
|
|
138
|
+
});
|
|
139
|
+
return group;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Leaves a group, removing all local state for it.
|
|
143
|
+
*/
|
|
144
|
+
leaveGroup(groupId) {
|
|
145
|
+
const state = this.requireGroupState(groupId);
|
|
146
|
+
// Remove self from the member list
|
|
147
|
+
state.group.members.delete(this.localPeerId);
|
|
148
|
+
state.senderKeys.delete(this.localPeerId);
|
|
149
|
+
state.keyIterations.delete(this.localPeerId);
|
|
150
|
+
state.activity.delete(this.localPeerId);
|
|
151
|
+
// Discard all local state for this group
|
|
152
|
+
this.groups.delete(groupId);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Returns the group with the given ID, or null if not found.
|
|
156
|
+
*/
|
|
157
|
+
getGroup(groupId) {
|
|
158
|
+
const state = this.groups.get(groupId);
|
|
159
|
+
return state?.group ?? null;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Returns all groups the local peer is participating in.
|
|
163
|
+
*/
|
|
164
|
+
getGroups() {
|
|
165
|
+
return Array.from(this.groups.values()).map((s) => s.group);
|
|
166
|
+
}
|
|
167
|
+
// ---- Member Management ----
|
|
168
|
+
/**
|
|
169
|
+
* Adds a new member to the group and generates a sender key for them.
|
|
170
|
+
*/
|
|
171
|
+
addMember(groupId, peerId) {
|
|
172
|
+
const state = this.requireGroupState(groupId);
|
|
173
|
+
if (state.group.members.has(peerId)) {
|
|
174
|
+
return; // Already a member
|
|
175
|
+
}
|
|
176
|
+
const now = Date.now();
|
|
177
|
+
const memberKey = this.generateSenderKey();
|
|
178
|
+
state.group.members.set(peerId, {
|
|
179
|
+
id: peerId,
|
|
180
|
+
senderKey: memberKey,
|
|
181
|
+
role: 'member',
|
|
182
|
+
joinedAt: now,
|
|
183
|
+
});
|
|
184
|
+
state.senderKeys.set(peerId, memberKey);
|
|
185
|
+
state.keyIterations.set(peerId, 0);
|
|
186
|
+
state.activity.set(peerId, { timestamps: [], lastActive: now });
|
|
187
|
+
// Invalidate cached tree
|
|
188
|
+
state.relayTree = null;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Removes a member from the group and triggers rotation of all sender keys
|
|
192
|
+
* to maintain forward secrecy — the removed member must not be able to
|
|
193
|
+
* decrypt future messages.
|
|
194
|
+
*/
|
|
195
|
+
removeMember(groupId, peerId) {
|
|
196
|
+
const state = this.requireGroupState(groupId);
|
|
197
|
+
if (!state.group.members.has(peerId)) {
|
|
198
|
+
return; // Not a member
|
|
199
|
+
}
|
|
200
|
+
state.group.members.delete(peerId);
|
|
201
|
+
state.senderKeys.delete(peerId);
|
|
202
|
+
state.keyIterations.delete(peerId);
|
|
203
|
+
state.activity.delete(peerId);
|
|
204
|
+
// Rotate all remaining sender keys (Signal protocol requirement)
|
|
205
|
+
this.rotateAllSenderKeys(groupId);
|
|
206
|
+
// Invalidate cached tree
|
|
207
|
+
state.relayTree = null;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Returns the list of all members in a group.
|
|
211
|
+
*/
|
|
212
|
+
getMembers(groupId) {
|
|
213
|
+
const state = this.requireGroupState(groupId);
|
|
214
|
+
return Array.from(state.group.members.values());
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Returns the role of a member in a group, or null if not a member.
|
|
218
|
+
*/
|
|
219
|
+
getMemberRole(groupId, peerId) {
|
|
220
|
+
const state = this.groups.get(groupId);
|
|
221
|
+
if (!state)
|
|
222
|
+
return null;
|
|
223
|
+
const member = state.group.members.get(peerId);
|
|
224
|
+
return member?.role ?? null;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Updates a member's role within the group.
|
|
228
|
+
*/
|
|
229
|
+
setMemberRole(groupId, peerId, role) {
|
|
230
|
+
const state = this.requireGroupState(groupId);
|
|
231
|
+
const member = state.group.members.get(peerId);
|
|
232
|
+
if (!member) {
|
|
233
|
+
throw new Error(`Peer ${peerId} is not a member of group ${groupId}`);
|
|
234
|
+
}
|
|
235
|
+
member.role = role;
|
|
236
|
+
}
|
|
237
|
+
// ---- Sender Keys ----
|
|
238
|
+
/**
|
|
239
|
+
* Generates a new 32-byte sender key using cryptographically secure randomness.
|
|
240
|
+
*/
|
|
241
|
+
generateSenderKey() {
|
|
242
|
+
return randomBytes(SENDER_KEY_LENGTH);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Creates a sender key distribution message for a specific recipient.
|
|
246
|
+
* This message should be encrypted via the pairwise channel before transmission.
|
|
247
|
+
*/
|
|
248
|
+
distributeSenderKey(groupId, senderKey, recipientId) {
|
|
249
|
+
const state = this.requireGroupState(groupId);
|
|
250
|
+
const iteration = state.keyIterations.get(this.localPeerId) ?? 0;
|
|
251
|
+
// Store locally
|
|
252
|
+
state.senderKeys.set(this.localPeerId, senderKey);
|
|
253
|
+
const member = state.group.members.get(this.localPeerId);
|
|
254
|
+
if (member) {
|
|
255
|
+
member.senderKey = senderKey;
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
groupId,
|
|
259
|
+
senderId: this.localPeerId,
|
|
260
|
+
senderKey,
|
|
261
|
+
iteration,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Processes a received sender key distribution message from another member.
|
|
266
|
+
*/
|
|
267
|
+
receiveSenderKey(distribution) {
|
|
268
|
+
const state = this.groups.get(distribution.groupId);
|
|
269
|
+
if (!state) {
|
|
270
|
+
throw new Error(`Unknown group ${distribution.groupId}`);
|
|
271
|
+
}
|
|
272
|
+
state.senderKeys.set(distribution.senderId, distribution.senderKey);
|
|
273
|
+
state.keyIterations.set(distribution.senderId, distribution.iteration);
|
|
274
|
+
const member = state.group.members.get(distribution.senderId);
|
|
275
|
+
if (member) {
|
|
276
|
+
member.senderKey = distribution.senderKey;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Rotates all sender keys in a group. Called when a member is removed
|
|
281
|
+
* to ensure forward secrecy.
|
|
282
|
+
*/
|
|
283
|
+
rotateAllSenderKeys(groupId) {
|
|
284
|
+
const state = this.requireGroupState(groupId);
|
|
285
|
+
for (const [peerId, member] of state.group.members) {
|
|
286
|
+
const newKey = this.generateSenderKey();
|
|
287
|
+
const currentIteration = state.keyIterations.get(peerId) ?? 0;
|
|
288
|
+
member.senderKey = newKey;
|
|
289
|
+
state.senderKeys.set(peerId, newKey);
|
|
290
|
+
state.keyIterations.set(peerId, currentIteration + 1);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Returns the sender key for a specific member in a group, or null if unknown.
|
|
295
|
+
*/
|
|
296
|
+
getSenderKey(groupId, memberId) {
|
|
297
|
+
const state = this.groups.get(groupId);
|
|
298
|
+
if (!state)
|
|
299
|
+
return null;
|
|
300
|
+
return state.senderKeys.get(memberId) ?? null;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Encrypts plaintext for the group using the local peer's sender key.
|
|
304
|
+
* Uses AES-256-GCM. The ciphertext format is: nonce (12) || ciphertext || tag (16).
|
|
305
|
+
*/
|
|
306
|
+
encryptForGroup(groupId, plaintext) {
|
|
307
|
+
const state = this.requireGroupState(groupId);
|
|
308
|
+
const senderKey = state.senderKeys.get(this.localPeerId);
|
|
309
|
+
if (!senderKey) {
|
|
310
|
+
throw new Error('No sender key available for local peer');
|
|
311
|
+
}
|
|
312
|
+
const nonce = randomBytes(GCM_NONCE_LENGTH);
|
|
313
|
+
const cipher = gcm(senderKey, nonce);
|
|
314
|
+
const sealed = cipher.encrypt(plaintext);
|
|
315
|
+
// Pack as: nonce || sealed (which is ciphertext || tag)
|
|
316
|
+
const result = new Uint8Array(GCM_NONCE_LENGTH + sealed.length);
|
|
317
|
+
result.set(nonce, 0);
|
|
318
|
+
result.set(sealed, GCM_NONCE_LENGTH);
|
|
319
|
+
// Record activity
|
|
320
|
+
this.updateActivity(groupId, this.localPeerId);
|
|
321
|
+
return { ciphertext: result, senderId: this.localPeerId };
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Decrypts a group message from a specific sender using their sender key.
|
|
325
|
+
* Expects the ciphertext format: nonce (12) || ciphertext || tag (16).
|
|
326
|
+
*/
|
|
327
|
+
decryptFromGroup(groupId, senderId, ciphertext) {
|
|
328
|
+
const state = this.requireGroupState(groupId);
|
|
329
|
+
const senderKey = state.senderKeys.get(senderId);
|
|
330
|
+
if (!senderKey) {
|
|
331
|
+
throw new Error(`No sender key for peer ${senderId} in group ${groupId}`);
|
|
332
|
+
}
|
|
333
|
+
if (ciphertext.length < GCM_NONCE_LENGTH + GCM_TAG_LENGTH) {
|
|
334
|
+
throw new Error('Ciphertext too short');
|
|
335
|
+
}
|
|
336
|
+
const nonce = ciphertext.slice(0, GCM_NONCE_LENGTH);
|
|
337
|
+
const sealed = ciphertext.slice(GCM_NONCE_LENGTH);
|
|
338
|
+
const cipher = gcm(senderKey, nonce);
|
|
339
|
+
return cipher.decrypt(sealed);
|
|
340
|
+
}
|
|
341
|
+
// ---- Dynamic Relay Tree ----
|
|
342
|
+
/**
|
|
343
|
+
* Records a message-send activity for a member. Used to compute
|
|
344
|
+
* activity scores that drive relay tree topology.
|
|
345
|
+
*/
|
|
346
|
+
updateActivity(groupId, peerId) {
|
|
347
|
+
const state = this.requireGroupState(groupId);
|
|
348
|
+
const record = state.activity.get(peerId);
|
|
349
|
+
if (!record)
|
|
350
|
+
return;
|
|
351
|
+
const now = Date.now();
|
|
352
|
+
record.timestamps.push(now);
|
|
353
|
+
record.lastActive = now;
|
|
354
|
+
// Prune timestamps older than the activity window
|
|
355
|
+
const cutoff = now - ACTIVITY_WINDOW_MS;
|
|
356
|
+
record.timestamps = record.timestamps.filter((t) => t >= cutoff);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Builds (or returns cached) relay tree for the group. The tree is
|
|
360
|
+
* structured so that the most active members form the trunk near the
|
|
361
|
+
* root, and less active members are leaves.
|
|
362
|
+
*
|
|
363
|
+
* The tree is rebuilt at most once per TREE_REBUILD_INTERVAL_MS.
|
|
364
|
+
*/
|
|
365
|
+
buildRelayTree(groupId) {
|
|
366
|
+
const state = this.requireGroupState(groupId);
|
|
367
|
+
const now = Date.now();
|
|
368
|
+
// Return cached tree if still fresh
|
|
369
|
+
if (state.relayTree &&
|
|
370
|
+
now - state.lastTreeBuild < TREE_REBUILD_INTERVAL_MS) {
|
|
371
|
+
return state.relayTree;
|
|
372
|
+
}
|
|
373
|
+
const memberIds = Array.from(state.group.members.keys());
|
|
374
|
+
if (memberIds.length === 0) {
|
|
375
|
+
throw new Error(`Group ${groupId} has no members`);
|
|
376
|
+
}
|
|
377
|
+
// Compute activity scores
|
|
378
|
+
const scores = new Map();
|
|
379
|
+
const cutoff = now - ACTIVITY_WINDOW_MS;
|
|
380
|
+
for (const peerId of memberIds) {
|
|
381
|
+
const record = state.activity.get(peerId);
|
|
382
|
+
if (!record) {
|
|
383
|
+
scores.set(peerId, 0);
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
const recentTimestamps = record.timestamps.filter((t) => t >= cutoff);
|
|
387
|
+
scores.set(peerId, recentTimestamps.length);
|
|
388
|
+
}
|
|
389
|
+
// Sort members by activity score descending; tie-break: tree root first, then ID
|
|
390
|
+
const sorted = [...memberIds].sort((a, b) => {
|
|
391
|
+
// Tree root (group creator) wins ties
|
|
392
|
+
if (a === state.group.treeRoot && b !== state.group.treeRoot)
|
|
393
|
+
return -1;
|
|
394
|
+
if (b === state.group.treeRoot && a !== state.group.treeRoot)
|
|
395
|
+
return 1;
|
|
396
|
+
const scoreA = scores.get(a) ?? 0;
|
|
397
|
+
const scoreB = scores.get(b) ?? 0;
|
|
398
|
+
if (scoreB !== scoreA)
|
|
399
|
+
return scoreB - scoreA;
|
|
400
|
+
return a.localeCompare(b);
|
|
401
|
+
});
|
|
402
|
+
// Build a balanced relay tree: most active peer is root, next most active
|
|
403
|
+
// peers fill the trunk (first children), less active are leaves.
|
|
404
|
+
// We use a breadth-first insertion approach to build a roughly balanced tree.
|
|
405
|
+
const nodeMap = new Map();
|
|
406
|
+
for (const peerId of sorted) {
|
|
407
|
+
const record = state.activity.get(peerId);
|
|
408
|
+
nodeMap.set(peerId, {
|
|
409
|
+
peerId,
|
|
410
|
+
children: [],
|
|
411
|
+
activityScore: scores.get(peerId) ?? 0,
|
|
412
|
+
lastActive: record?.lastActive ?? 0,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
const root = nodeMap.get(sorted[0]);
|
|
416
|
+
// BFS queue for balanced insertion — each node gets at most 2 children
|
|
417
|
+
// to keep tree depth logarithmic
|
|
418
|
+
const MAX_CHILDREN = 2;
|
|
419
|
+
const queue = [root];
|
|
420
|
+
let queueIdx = 0;
|
|
421
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
422
|
+
const child = nodeMap.get(sorted[i]);
|
|
423
|
+
// Find the next parent with capacity
|
|
424
|
+
while (queueIdx < queue.length && queue[queueIdx].children.length >= MAX_CHILDREN) {
|
|
425
|
+
queueIdx++;
|
|
426
|
+
}
|
|
427
|
+
if (queueIdx < queue.length) {
|
|
428
|
+
queue[queueIdx].children.push(child);
|
|
429
|
+
queue.push(child);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
state.relayTree = root;
|
|
433
|
+
state.lastTreeBuild = now;
|
|
434
|
+
return root;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Determines which peer should relay a message to reach the target peer.
|
|
438
|
+
* Returns the parent of the target in the relay tree, or null if the
|
|
439
|
+
* target is the root or not found.
|
|
440
|
+
*/
|
|
441
|
+
getRelayTarget(groupId, targetPeerId) {
|
|
442
|
+
const tree = this.buildRelayTree(groupId);
|
|
443
|
+
// BFS to find the parent of the target
|
|
444
|
+
const queue = [
|
|
445
|
+
{ node: tree, parent: null },
|
|
446
|
+
];
|
|
447
|
+
while (queue.length > 0) {
|
|
448
|
+
const { node, parent } = queue.shift();
|
|
449
|
+
if (node.peerId === targetPeerId) {
|
|
450
|
+
return parent?.peerId ?? null;
|
|
451
|
+
}
|
|
452
|
+
for (const child of node.children) {
|
|
453
|
+
queue.push({ node: child, parent: node });
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Returns the list of peer IDs that the local peer should relay messages to
|
|
460
|
+
* (i.e., the local peer's children in the relay tree).
|
|
461
|
+
*/
|
|
462
|
+
getRelayChildren(groupId) {
|
|
463
|
+
const tree = this.buildRelayTree(groupId);
|
|
464
|
+
const localNode = this.findNodeInTree(tree, this.localPeerId);
|
|
465
|
+
if (!localNode)
|
|
466
|
+
return [];
|
|
467
|
+
return localNode.children.map((c) => c.peerId);
|
|
468
|
+
}
|
|
469
|
+
// ---- Group Message Routing ----
|
|
470
|
+
/**
|
|
471
|
+
* Routes a group message through the relay tree. Returns the list of peers
|
|
472
|
+
* that the local peer should forward the message to, based on the relay
|
|
473
|
+
* tree position.
|
|
474
|
+
*
|
|
475
|
+
* If the local peer is the sender (or root), it forwards to its children.
|
|
476
|
+
* If the local peer is relaying, it forwards to its children plus its parent
|
|
477
|
+
* (if the message didn't come from the parent direction).
|
|
478
|
+
*/
|
|
479
|
+
routeGroupMessage(groupId, ciphertext, senderId) {
|
|
480
|
+
const tree = this.buildRelayTree(groupId);
|
|
481
|
+
const localNode = this.findNodeInTree(tree, this.localPeerId);
|
|
482
|
+
if (!localNode)
|
|
483
|
+
return [];
|
|
484
|
+
const targets = [];
|
|
485
|
+
// Collect all descendants that should receive the relay
|
|
486
|
+
const collectDescendants = (node) => {
|
|
487
|
+
for (const child of node.children) {
|
|
488
|
+
if (child.peerId !== senderId) {
|
|
489
|
+
targets.push({ peerId: child.peerId, data: ciphertext });
|
|
490
|
+
}
|
|
491
|
+
collectDescendants(child);
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
// If we are the sender, relay to all our tree children subtrees
|
|
495
|
+
if (senderId === this.localPeerId) {
|
|
496
|
+
for (const child of localNode.children) {
|
|
497
|
+
targets.push({ peerId: child.peerId, data: ciphertext });
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
// We are relaying — forward to our children (excluding the sender direction)
|
|
502
|
+
for (const child of localNode.children) {
|
|
503
|
+
if (child.peerId !== senderId && !this.isInSubtree(child, senderId)) {
|
|
504
|
+
targets.push({ peerId: child.peerId, data: ciphertext });
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
// Also forward to parent if the message came from a child
|
|
508
|
+
const parent = this.findParentInTree(tree, this.localPeerId);
|
|
509
|
+
if (parent && parent.peerId !== senderId) {
|
|
510
|
+
targets.push({ peerId: parent.peerId, data: ciphertext });
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return targets;
|
|
514
|
+
}
|
|
515
|
+
// ---- Private Helpers ----
|
|
516
|
+
/** Generates a random hex-encoded group ID. */
|
|
517
|
+
generateGroupId() {
|
|
518
|
+
const bytes = randomBytes(GROUP_ID_LENGTH);
|
|
519
|
+
return Array.from(bytes)
|
|
520
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
521
|
+
.join('');
|
|
522
|
+
}
|
|
523
|
+
/** Retrieves group state or throws if the group is unknown. */
|
|
524
|
+
requireGroupState(groupId) {
|
|
525
|
+
const state = this.groups.get(groupId);
|
|
526
|
+
if (!state) {
|
|
527
|
+
throw new Error(`Unknown group ${groupId}`);
|
|
528
|
+
}
|
|
529
|
+
return state;
|
|
530
|
+
}
|
|
531
|
+
/** Searches the relay tree for a node by peer ID. */
|
|
532
|
+
findNodeInTree(root, peerId) {
|
|
533
|
+
if (root.peerId === peerId)
|
|
534
|
+
return root;
|
|
535
|
+
for (const child of root.children) {
|
|
536
|
+
const found = this.findNodeInTree(child, peerId);
|
|
537
|
+
if (found)
|
|
538
|
+
return found;
|
|
539
|
+
}
|
|
540
|
+
return null;
|
|
541
|
+
}
|
|
542
|
+
/** Finds the parent node of a given peer in the relay tree. */
|
|
543
|
+
findParentInTree(root, peerId) {
|
|
544
|
+
for (const child of root.children) {
|
|
545
|
+
if (child.peerId === peerId)
|
|
546
|
+
return root;
|
|
547
|
+
const found = this.findParentInTree(child, peerId);
|
|
548
|
+
if (found)
|
|
549
|
+
return found;
|
|
550
|
+
}
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
/** Checks whether a peer is anywhere in the subtree rooted at the given node. */
|
|
554
|
+
isInSubtree(node, peerId) {
|
|
555
|
+
if (node.peerId === peerId)
|
|
556
|
+
return true;
|
|
557
|
+
return node.children.some((child) => this.isInSubtree(child, peerId));
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/group/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { MeshWhisper, GroupHandle } from './sdk/index.js';
|
|
2
|
+
export type { SendOptions, CreateGroupOptions, TransportChangedEvent } from './sdk/index.js';
|
|
3
|
+
export type { KeyPair, PreKeyBundle, EncryptedPayload, Packet, BearerType, BatteryState, RelayWillingness, DeviceCapability, Transport, PeerProximityEntry, RouteRequest, RouteOffer, PermissionModel, Session, MessageUrgency, PresenceStatus, Message, GroupMember, Group, RelayLedgerEntry, ReciprocityTier, ClusterDevice, StoredBlob, EntropySensorType, EntropyChallenge, EntropyResponse, ChaffRate, AuditExportMode, ComplianceConfig, MessageHook, MeshWhisperConfig, NamespaceConfig, EventEmitter, } from './types.js';
|
|
4
|
+
export { PacketFlags } from './types.js';
|
|
5
|
+
export type { PlatformP2PBridge, PeerInfo } from './transport/p2p/index.js';
|
|
6
|
+
export { registerPlatformBridge } from './transport/p2p/index.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAI7F,YAAY,EAEV,OAAO,EACP,YAAY,EACZ,gBAAgB,EAGhB,MAAM,EAGN,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,EAGT,kBAAkB,EAClB,YAAY,EACZ,UAAU,EAGV,eAAe,EACf,OAAO,EAGP,cAAc,EACd,cAAc,EACd,OAAO,EAGP,WAAW,EACX,KAAK,EAGL,gBAAgB,EAChB,eAAe,EAGf,aAAa,EAGb,UAAU,EAGV,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EAGf,SAAS,EAGT,eAAe,EACf,gBAAgB,EAChB,WAAW,EAGX,iBAAiB,EAGjB,eAAe,EAGf,YAAY,GACb,MAAM,YAAY,CAAC;AAIpB,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAIzC,YAAY,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// MeshWhisper SDK — Main Entry Point
|
|
3
|
+
// Re-exports the public API surface and all public types.
|
|
4
|
+
// ============================================================
|
|
5
|
+
// --- Primary SDK class ---
|
|
6
|
+
export { MeshWhisper, GroupHandle } from './sdk/index.js';
|
|
7
|
+
// Re-export PacketFlags as a value (enum) since it is used as both
|
|
8
|
+
// a type and a runtime value.
|
|
9
|
+
export { PacketFlags } from './types.js';
|
|
10
|
+
export { registerPlatformBridge } from './transport/p2p/index.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,qCAAqC;AACrC,0DAA0D;AAC1D,+DAA+D;AAE/D,4BAA4B;AAE5B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAwE1D,mEAAmE;AACnE,8BAA8B;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAKzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC"}
|