@agora-sdk/secure-chat-crypto 0.3.0 → 0.5.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/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.js +4 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interface.d.ts +77 -1
- package/dist/cjs/interface.js +19 -0
- package/dist/cjs/interface.js.map +1 -1
- package/dist/cjs/mock-crypto.d.ts +4 -3
- package/dist/cjs/mock-crypto.js +54 -9
- package/dist/cjs/mock-crypto.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interface.d.ts +77 -1
- package/dist/esm/interface.js +17 -1
- package/dist/esm/interface.js.map +1 -1
- package/dist/esm/mock-crypto.d.ts +4 -3
- package/dist/esm/mock-crypto.js +54 -9
- package/dist/esm/mock-crypto.js.map +1 -1
- package/dist/esm/ts-mls/backup.d.ts +30 -0
- package/dist/esm/ts-mls/backup.js +105 -0
- package/dist/esm/ts-mls/backup.js.map +1 -0
- package/dist/esm/ts-mls/ciphersuite.d.ts +26 -0
- package/dist/esm/ts-mls/ciphersuite.js +41 -0
- package/dist/esm/ts-mls/ciphersuite.js.map +1 -0
- package/dist/esm/ts-mls/crypto.d.ts +103 -0
- package/dist/esm/ts-mls/crypto.js +363 -0
- package/dist/esm/ts-mls/crypto.js.map +1 -0
- package/dist/esm/ts-mls/hex.d.ts +4 -0
- package/dist/esm/ts-mls/hex.js +18 -0
- package/dist/esm/ts-mls/hex.js.map +1 -0
- package/dist/esm/ts-mls/index.d.ts +15 -0
- package/dist/esm/ts-mls/index.js +21 -0
- package/dist/esm/ts-mls/index.js.map +1 -0
- package/package.json +12 -2
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
// TsMlsSecureChatCrypto — the real RFC 9420 implementation of the SecureChatCrypto seam, on ts-mls.
|
|
2
|
+
//
|
|
3
|
+
// Where it sits in the blind-server model: ALL MLS crypto is here, client-side. Only ciphertext,
|
|
4
|
+
// public KeyPackages, and Welcomes/Commits ever cross the wire; group secrets and private keys never
|
|
5
|
+
// leave this object. It mirrors MockSecureChatCrypto's shape — an in-memory Map<groupIdHex, ClientState>
|
|
6
|
+
// keyed by GroupHandle.mlsGroupId — so the interface and all call sites are unchanged.
|
|
7
|
+
//
|
|
8
|
+
// Security (CLAUDE.md #1): randomness is the platform CSPRNG (crypto.getRandomValues) + ts-mls/@noble;
|
|
9
|
+
// failed decode/decrypt/join fail closed (throw, drop); consumed key material is zeroized.
|
|
10
|
+
import { generateKeyPackageWithKey, defaultCapabilities, defaultLifetime, createGroup, createCommit, joinGroup, createApplicationMessage, processMessage, encodeMlsMessage, decodeMlsMessage, encodeGroupState, decodeGroupState, zeroOutUint8Array, acceptAll, emptyPskIndex, defaultKeyRetentionConfig, } from "ts-mls";
|
|
11
|
+
// makeKeyPackageRef + getGroupMembers + defaultClientConfig aren't re-exported from the package root;
|
|
12
|
+
// ts-mls exposes every module via its "./*.js" export, so deep-import them.
|
|
13
|
+
import { makeKeyPackageRef } from "ts-mls/keyPackage.js";
|
|
14
|
+
import { getGroupMembers } from "ts-mls/clientState.js";
|
|
15
|
+
import { defaultClientConfig } from "ts-mls/clientConfig.js";
|
|
16
|
+
import { SecureChatDecryptError } from "../interface.js";
|
|
17
|
+
import { DEFAULT_CIPHERSUITE_ID, loadCiphersuite } from "./ciphersuite.js";
|
|
18
|
+
import { sealBackup, openBackup } from "./backup.js";
|
|
19
|
+
import { toHex, fromHex } from "./hex.js";
|
|
20
|
+
const utf8 = (s) => new TextEncoder().encode(s);
|
|
21
|
+
const MLS_VERSION = "mls10";
|
|
22
|
+
/**
|
|
23
|
+
* Map a ts-mls decrypt/process failure to a {@link SecureChatDecryptError} with a classified reason.
|
|
24
|
+
* Matches on ts-mls's error messages/names (its secret-tree ratchet is the actual enforcement). The
|
|
25
|
+
* returned message is generic-by-reason — we never echo internal bytes or plaintext into the error.
|
|
26
|
+
*/
|
|
27
|
+
function classifyDecryptError(err) {
|
|
28
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
29
|
+
const name = err instanceof Error ? err.name : "";
|
|
30
|
+
let reason = "unknown";
|
|
31
|
+
if (/desired gen(?:eration)? in the past/i.test(msg))
|
|
32
|
+
reason = "replay";
|
|
33
|
+
else if (/too far in the future/i.test(msg))
|
|
34
|
+
reason = "gap-too-large";
|
|
35
|
+
else if (/epoch too old|former epoch/i.test(msg))
|
|
36
|
+
reason = "epoch-too-old";
|
|
37
|
+
else if (name === "CryptoVerificationError" || /signature|verif|auth/i.test(msg))
|
|
38
|
+
reason = "unauthenticated";
|
|
39
|
+
else if (name === "CodecError" || /decode|malformed/i.test(msg))
|
|
40
|
+
reason = "malformed";
|
|
41
|
+
return new SecureChatDecryptError(reason, `secure-chat: message decrypt rejected (${reason})`);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Real RFC 9420 MLS implementation of {@link SecureChatCrypto}, built on ts-mls. Construct via
|
|
45
|
+
* `createTsMlsSecureChatCrypto`; inject into `<SecureChatProvider crypto={…}>`.
|
|
46
|
+
*/
|
|
47
|
+
export class TsMlsSecureChatCrypto {
|
|
48
|
+
constructor(options = {}) {
|
|
49
|
+
this.csImpl = null;
|
|
50
|
+
this.pending = new Map(); // hex(ref) → kp
|
|
51
|
+
this.groups = new Map(); // hex(groupId) → state
|
|
52
|
+
this.ciphersuiteId = options.ciphersuite ?? DEFAULT_CIPHERSUITE_ID;
|
|
53
|
+
this.clientConfig = {
|
|
54
|
+
...defaultClientConfig,
|
|
55
|
+
keyRetentionConfig: { ...defaultKeyRetentionConfig, ...options.keyRetention },
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** Lazily load + memoize the ciphersuite primitives. */
|
|
59
|
+
async cs() {
|
|
60
|
+
if (!this.csImpl)
|
|
61
|
+
this.csImpl = await loadCiphersuite(this.ciphersuiteId);
|
|
62
|
+
return this.csImpl;
|
|
63
|
+
}
|
|
64
|
+
requireDevice() {
|
|
65
|
+
if (!this.device || !this.credential) {
|
|
66
|
+
throw new Error("secure-chat: no device identity (call generateDeviceIdentity or importDeviceState first)");
|
|
67
|
+
}
|
|
68
|
+
return this.device;
|
|
69
|
+
}
|
|
70
|
+
async generateDeviceIdentity(opts) {
|
|
71
|
+
const cs = await this.cs();
|
|
72
|
+
const { publicKey, signKey } = await cs.signature.keygen();
|
|
73
|
+
const credential = { credentialType: "basic", identity: utf8(opts.deviceId) };
|
|
74
|
+
this.device = { deviceId: opts.deviceId, ciphersuite: this.ciphersuiteId, signKey, publicKey };
|
|
75
|
+
this.credential = credential;
|
|
76
|
+
const identity = {
|
|
77
|
+
deviceId: opts.deviceId,
|
|
78
|
+
signaturePublicKey: publicKey,
|
|
79
|
+
credential: utf8(opts.deviceId), // opaque to the blind server; peers use the claimed KeyPackage
|
|
80
|
+
ciphersuite: this.ciphersuiteId,
|
|
81
|
+
};
|
|
82
|
+
return { identity, privateState: this.serializeDeviceState() };
|
|
83
|
+
}
|
|
84
|
+
async generateKeyPackages(count) {
|
|
85
|
+
const cs = await this.cs();
|
|
86
|
+
const dev = this.requireDevice();
|
|
87
|
+
const out = [];
|
|
88
|
+
for (let i = 0; i < count; i++) {
|
|
89
|
+
const { publicPackage, privatePackage } = await generateKeyPackageWithKey(this.credential, defaultCapabilities(), defaultLifetime, [], { signKey: dev.signKey, publicKey: dev.publicKey }, cs);
|
|
90
|
+
const ref = await makeKeyPackageRef(publicPackage, cs.hash);
|
|
91
|
+
const refHex = toHex(ref);
|
|
92
|
+
this.pending.set(refHex, { publicPackage, privatePackage });
|
|
93
|
+
out.push({
|
|
94
|
+
keyPackageRef: refHex,
|
|
95
|
+
keyPackage: encodeMlsMessage({ version: MLS_VERSION, wireformat: "mls_key_package", keyPackage: publicPackage }),
|
|
96
|
+
ciphersuite: dev.ciphersuite,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
async createGroup(opts) {
|
|
102
|
+
const cs = await this.cs();
|
|
103
|
+
const dev = this.requireDevice();
|
|
104
|
+
const groupId = opts.mlsGroupId ?? crypto.getRandomValues(new Uint8Array(32));
|
|
105
|
+
// Seed the group with a fresh self KeyPackage (local-only; never published).
|
|
106
|
+
const self = await generateKeyPackageWithKey(this.credential, defaultCapabilities(), defaultLifetime, [], { signKey: dev.signKey, publicKey: dev.publicKey }, cs);
|
|
107
|
+
let state = await createGroup(groupId, self.publicPackage, self.privatePackage, [], cs, this.clientConfig);
|
|
108
|
+
const adds = opts.initialMembers.map((m) => ({
|
|
109
|
+
proposalType: "add", add: { keyPackage: this.decodeKeyPackage(m.keyPackage) },
|
|
110
|
+
}));
|
|
111
|
+
const commit = await createCommit({ state, cipherSuite: cs }, { extraProposals: adds, ratchetTreeExtension: true });
|
|
112
|
+
state = commit.newState;
|
|
113
|
+
this.zeroize(commit.consumed);
|
|
114
|
+
this.groups.set(toHex(groupId), state);
|
|
115
|
+
// ratchetTreeExtension:true → the tree rides inside the Welcome, so a recipient joins from it ALONE.
|
|
116
|
+
const welcomeBytes = encodeMlsMessage({ version: MLS_VERSION, wireformat: "mls_welcome", welcome: commit.welcome });
|
|
117
|
+
const welcomes = opts.initialMembers.map((m) => ({ targetDeviceId: m.deviceId, payload: welcomeBytes }));
|
|
118
|
+
return { group: { mlsGroupId: groupId, epoch: state.groupContext.epoch }, welcomes };
|
|
119
|
+
}
|
|
120
|
+
async addMember(group, newDevice) {
|
|
121
|
+
const cs = await this.cs();
|
|
122
|
+
const state = this.lookupGroup(group);
|
|
123
|
+
const commit = await createCommit({ state, cipherSuite: cs }, { extraProposals: [{ proposalType: "add", add: { keyPackage: this.decodeKeyPackage(newDevice.keyPackage) } }], ratchetTreeExtension: true });
|
|
124
|
+
this.zeroize(commit.consumed);
|
|
125
|
+
this.groups.set(toHex(group.mlsGroupId), commit.newState);
|
|
126
|
+
return {
|
|
127
|
+
commit: encodeMlsMessage(commit.commit),
|
|
128
|
+
welcomes: [{
|
|
129
|
+
targetDeviceId: newDevice.deviceId,
|
|
130
|
+
payload: encodeMlsMessage({ version: MLS_VERSION, wireformat: "mls_welcome", welcome: commit.welcome }),
|
|
131
|
+
}],
|
|
132
|
+
epoch: commit.newState.groupContext.epoch,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Membership churn (remove/leave) is Phase 3 (multi-device). Fail closed rather than ship untested
|
|
136
|
+
// leaf-index handling: the DM happy path never calls this.
|
|
137
|
+
removeMember(_group, _leafDeviceId) {
|
|
138
|
+
throw new Error("secure-chat: removeMember is not implemented in the Phase 2 web core (Phase 3)");
|
|
139
|
+
}
|
|
140
|
+
async encryptMessage(group, plaintext) {
|
|
141
|
+
const cs = await this.cs();
|
|
142
|
+
const state = this.lookupGroup(group);
|
|
143
|
+
const res = await createApplicationMessage(state, plaintext, cs);
|
|
144
|
+
this.zeroize(res.consumed);
|
|
145
|
+
this.groups.set(toHex(group.mlsGroupId), res.newState);
|
|
146
|
+
return {
|
|
147
|
+
ciphertext: encodeMlsMessage({ version: MLS_VERSION, wireformat: "mls_private_message", privateMessage: res.privateMessage }),
|
|
148
|
+
epoch: res.newState.groupContext.epoch,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
async decryptMessage(group, ciphertext) {
|
|
152
|
+
const cs = await this.cs();
|
|
153
|
+
const state = this.lookupGroup(group);
|
|
154
|
+
// ts-mls's secret-tree ratchet is the enforcement point: it throws on a replayed generation, an
|
|
155
|
+
// over-limit forward gap, a too-old epoch, or a failed authentication. We classify that throw (and
|
|
156
|
+
// decode failures) into a SecureChatDecryptError and re-raise it — and crucially we do NOT advance
|
|
157
|
+
// stored group state on failure (processMessage threw before returning newState), so a rejected
|
|
158
|
+
// message never ratchets us forward. Fail closed.
|
|
159
|
+
let res;
|
|
160
|
+
try {
|
|
161
|
+
const decoded = decodeMlsMessage(ciphertext, 0);
|
|
162
|
+
if (!decoded)
|
|
163
|
+
throw new SecureChatDecryptError("malformed", "secure-chat: malformed MLS message");
|
|
164
|
+
res = await processMessage(decoded[0], state, emptyPskIndex, acceptAll, cs);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
throw err instanceof SecureChatDecryptError ? err : classifyDecryptError(err);
|
|
168
|
+
}
|
|
169
|
+
this.zeroize(res.consumed);
|
|
170
|
+
this.groups.set(toHex(group.mlsGroupId), res.newState);
|
|
171
|
+
if (res.kind !== "applicationMessage") {
|
|
172
|
+
throw new SecureChatDecryptError("malformed", "secure-chat: expected an application message");
|
|
173
|
+
}
|
|
174
|
+
return { plaintext: res.message, senderDeviceId: this.peerDeviceId(res.newState), epoch: res.newState.groupContext.epoch };
|
|
175
|
+
}
|
|
176
|
+
async exportGroupIdentities(group) {
|
|
177
|
+
const state = this.lookupGroup(group);
|
|
178
|
+
const out = [];
|
|
179
|
+
// Read the roster from the MLS ratchet tree (same source peerDeviceId uses). Only basic-credential
|
|
180
|
+
// leaves carry a device-id identity; skip anything else rather than guess.
|
|
181
|
+
for (const leaf of getGroupMembers(state)) {
|
|
182
|
+
if (leaf.credential.credentialType !== "basic")
|
|
183
|
+
continue;
|
|
184
|
+
out.push({
|
|
185
|
+
deviceId: new TextDecoder().decode(leaf.credential.identity),
|
|
186
|
+
signaturePublicKey: leaf.signaturePublicKey,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
return out;
|
|
190
|
+
}
|
|
191
|
+
async processWelcome(welcomePayload) {
|
|
192
|
+
const cs = await this.cs();
|
|
193
|
+
const decoded = decodeMlsMessage(welcomePayload, 0);
|
|
194
|
+
if (!decoded || decoded[0].wireformat !== "mls_welcome")
|
|
195
|
+
throw new Error("secure-chat: malformed Welcome");
|
|
196
|
+
const welcome = decoded[0].welcome;
|
|
197
|
+
// Match the Welcome to one of our pending KeyPackages by its MLS ref (welcome.secrets[].newMember).
|
|
198
|
+
let matchedRef;
|
|
199
|
+
let matched;
|
|
200
|
+
for (const s of welcome.secrets) {
|
|
201
|
+
const refHex = toHex(s.newMember);
|
|
202
|
+
const kp = this.pending.get(refHex);
|
|
203
|
+
if (kp) {
|
|
204
|
+
matchedRef = refHex;
|
|
205
|
+
matched = kp;
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (!matched || !matchedRef)
|
|
210
|
+
throw new Error("secure-chat: no matching KeyPackage for this Welcome");
|
|
211
|
+
// ratchetTree omitted — it rode in via the creator's ratchetTreeExtension. Pass our clientConfig
|
|
212
|
+
// (positional args 6/7 — ratchetTree/resumingFromState — are unused here) so the joined group gets
|
|
213
|
+
// the configured key-retention window, not ts-mls's default.
|
|
214
|
+
const state = await joinGroup(welcome, matched.publicPackage, matched.privatePackage, emptyPskIndex, cs, undefined, undefined, this.clientConfig);
|
|
215
|
+
this.pending.delete(matchedRef); // one-time: consumed
|
|
216
|
+
this.groups.set(toHex(state.groupContext.groupId), state);
|
|
217
|
+
return { mlsGroupId: state.groupContext.groupId, epoch: state.groupContext.epoch };
|
|
218
|
+
}
|
|
219
|
+
async processCommit(group, commit) {
|
|
220
|
+
const cs = await this.cs();
|
|
221
|
+
const state = this.lookupGroup(group);
|
|
222
|
+
const decoded = decodeMlsMessage(commit, 0);
|
|
223
|
+
if (!decoded)
|
|
224
|
+
throw new Error("secure-chat: malformed commit");
|
|
225
|
+
const res = await processMessage(decoded[0], state, emptyPskIndex, acceptAll, cs);
|
|
226
|
+
this.zeroize(res.consumed);
|
|
227
|
+
if (res.kind !== "newState")
|
|
228
|
+
throw new Error("secure-chat: expected a commit/proposal, got an application message");
|
|
229
|
+
this.groups.set(toHex(group.mlsGroupId), res.newState);
|
|
230
|
+
return { mlsGroupId: group.mlsGroupId, epoch: res.newState.groupContext.epoch };
|
|
231
|
+
}
|
|
232
|
+
async processProposal(group, proposal) {
|
|
233
|
+
const cs = await this.cs();
|
|
234
|
+
const state = this.lookupGroup(group);
|
|
235
|
+
const decoded = decodeMlsMessage(proposal, 0);
|
|
236
|
+
if (!decoded)
|
|
237
|
+
throw new Error("secure-chat: malformed proposal");
|
|
238
|
+
const res = await processMessage(decoded[0], state, emptyPskIndex, acceptAll, cs);
|
|
239
|
+
this.zeroize(res.consumed);
|
|
240
|
+
if (res.kind === "newState")
|
|
241
|
+
this.groups.set(toHex(group.mlsGroupId), res.newState);
|
|
242
|
+
}
|
|
243
|
+
async exportGroupState(group) {
|
|
244
|
+
// ClientState = GroupState & { clientConfig }. encodeGroupState serializes the GroupState; the
|
|
245
|
+
// clientConfig (which holds non-serializable callbacks) is reattached from the default on import.
|
|
246
|
+
return encodeGroupState(this.lookupGroup(group));
|
|
247
|
+
}
|
|
248
|
+
async importGroupState(state) {
|
|
249
|
+
const decoded = decodeGroupState(state, 0);
|
|
250
|
+
if (!decoded)
|
|
251
|
+
throw new Error("secure-chat: corrupt group state");
|
|
252
|
+
// Reattach OUR clientConfig (not ts-mls's default) so the configured key-retention window survives
|
|
253
|
+
// the persistence round-trip — encodeGroupState drops the (callback-bearing) config.
|
|
254
|
+
const clientState = { ...decoded[0], clientConfig: this.clientConfig };
|
|
255
|
+
this.groups.set(toHex(clientState.groupContext.groupId), clientState);
|
|
256
|
+
return { mlsGroupId: clientState.groupContext.groupId, epoch: clientState.groupContext.epoch };
|
|
257
|
+
}
|
|
258
|
+
async exportDeviceState() {
|
|
259
|
+
return this.serializeDeviceState();
|
|
260
|
+
}
|
|
261
|
+
async importDeviceState(state) {
|
|
262
|
+
const p = JSON.parse(new TextDecoder().decode(state));
|
|
263
|
+
if (p.v !== 1)
|
|
264
|
+
throw new Error(`secure-chat: unsupported device-state version ${p.v}`);
|
|
265
|
+
this.device = {
|
|
266
|
+
deviceId: p.deviceId, ciphersuite: p.ciphersuite, signKey: fromHex(p.signKey), publicKey: fromHex(p.publicKey),
|
|
267
|
+
};
|
|
268
|
+
this.credential = { credentialType: "basic", identity: utf8(p.deviceId) };
|
|
269
|
+
this.pending.clear();
|
|
270
|
+
for (const e of p.pending) {
|
|
271
|
+
this.pending.set(e.ref, {
|
|
272
|
+
publicPackage: this.decodeKeyPackage(fromHex(e.publicPackage)),
|
|
273
|
+
privatePackage: {
|
|
274
|
+
initPrivateKey: fromHex(e.initPrivateKey),
|
|
275
|
+
hpkePrivateKey: fromHex(e.hpkePrivateKey),
|
|
276
|
+
signaturePrivateKey: fromHex(e.signaturePrivateKey),
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
return { deviceId: p.deviceId, signaturePublicKey: this.device.publicKey, credential: utf8(p.deviceId), ciphersuite: p.ciphersuite };
|
|
281
|
+
}
|
|
282
|
+
// Passphrase backup of ALL local key material: the device identity (incl. the signature private
|
|
283
|
+
// key + pending KeyPackages, via serializeDeviceState) and every joined group's full MLS state.
|
|
284
|
+
// The argon2id KDF + AEAD live in ./backup.ts; here we just (de)serialize the payload. The blob is
|
|
285
|
+
// opaque to the blind server — only ciphertext crosses the wire.
|
|
286
|
+
async exportBackup(passphrase) {
|
|
287
|
+
const payload = {
|
|
288
|
+
v: 1,
|
|
289
|
+
device: toHex(this.serializeDeviceState()),
|
|
290
|
+
groups: [...this.groups.values()].map((st) => toHex(encodeGroupState(st))),
|
|
291
|
+
};
|
|
292
|
+
return sealBackup(utf8(JSON.stringify(payload)), passphrase);
|
|
293
|
+
}
|
|
294
|
+
async importBackup(passphrase, backup) {
|
|
295
|
+
const plain = await openBackup(backup, passphrase);
|
|
296
|
+
const payload = JSON.parse(new TextDecoder().decode(plain));
|
|
297
|
+
if (payload.v !== 1)
|
|
298
|
+
throw new Error(`secure-chat: unsupported backup payload version ${payload.v}`);
|
|
299
|
+
// Restore the device identity first (also clears + repopulates the pending KeyPackages).
|
|
300
|
+
const identity = await this.importDeviceState(fromHex(payload.device));
|
|
301
|
+
// Then every group's full state, keyed by its MLS group id (mirrors importGroupState).
|
|
302
|
+
for (const g of payload.groups) {
|
|
303
|
+
const decoded = decodeGroupState(fromHex(g), 0);
|
|
304
|
+
if (!decoded)
|
|
305
|
+
throw new Error("secure-chat: corrupt group state in backup");
|
|
306
|
+
const clientState = { ...decoded[0], clientConfig: this.clientConfig };
|
|
307
|
+
this.groups.set(toHex(clientState.groupContext.groupId), clientState);
|
|
308
|
+
}
|
|
309
|
+
return identity;
|
|
310
|
+
}
|
|
311
|
+
/** Serialize identity (incl. signature private key) + the pending KeyPackage store to an opaque blob. */
|
|
312
|
+
serializeDeviceState() {
|
|
313
|
+
const dev = this.requireDevice();
|
|
314
|
+
const payload = {
|
|
315
|
+
v: 1,
|
|
316
|
+
deviceId: dev.deviceId,
|
|
317
|
+
ciphersuite: dev.ciphersuite,
|
|
318
|
+
signKey: toHex(dev.signKey),
|
|
319
|
+
publicKey: toHex(dev.publicKey),
|
|
320
|
+
pending: [...this.pending.entries()].map(([ref, kp]) => ({
|
|
321
|
+
ref,
|
|
322
|
+
publicPackage: toHex(encodeMlsMessage({ version: MLS_VERSION, wireformat: "mls_key_package", keyPackage: kp.publicPackage })),
|
|
323
|
+
initPrivateKey: toHex(kp.privatePackage.initPrivateKey),
|
|
324
|
+
hpkePrivateKey: toHex(kp.privatePackage.hpkePrivateKey),
|
|
325
|
+
signaturePrivateKey: toHex(kp.privatePackage.signaturePrivateKey),
|
|
326
|
+
})),
|
|
327
|
+
};
|
|
328
|
+
return utf8(JSON.stringify(payload));
|
|
329
|
+
}
|
|
330
|
+
// Best-effort sender attribution for a DM: the one member that isn't us. Real per-message sender
|
|
331
|
+
// attribution for >2-member groups arrives with multi-device (Phase 3); the server also attests
|
|
332
|
+
// senderDeviceId on the message row independently, so a "" here degrades gracefully.
|
|
333
|
+
peerDeviceId(state) {
|
|
334
|
+
try {
|
|
335
|
+
const me = toHex(this.device.publicKey);
|
|
336
|
+
for (const leaf of getGroupMembers(state)) {
|
|
337
|
+
if (leaf.credential.credentialType === "basic" && toHex(leaf.signaturePublicKey) !== me) {
|
|
338
|
+
return new TextDecoder().decode(leaf.credential.identity);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
/* fall through to unknown */
|
|
344
|
+
}
|
|
345
|
+
return "";
|
|
346
|
+
}
|
|
347
|
+
// Helpers used across tasks 4–5.
|
|
348
|
+
/** @internal */ zeroize(consumed) { for (const c of consumed)
|
|
349
|
+
zeroOutUint8Array(c); }
|
|
350
|
+
/** @internal */ lookupGroup(group) {
|
|
351
|
+
const state = this.groups.get(toHex(group.mlsGroupId));
|
|
352
|
+
if (!state)
|
|
353
|
+
throw new Error("secure-chat: unknown group (not joined or evicted)");
|
|
354
|
+
return state;
|
|
355
|
+
}
|
|
356
|
+
/** @internal */ decodeKeyPackage(bytes) {
|
|
357
|
+
const d = decodeMlsMessage(bytes, 0);
|
|
358
|
+
if (!d || d[0].wireformat !== "mls_key_package")
|
|
359
|
+
throw new Error("secure-chat: malformed KeyPackage");
|
|
360
|
+
return d[0].keyPackage;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../../src/ts-mls/crypto.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Local hex helpers so this package stays free of the core's base64 (the seam works in Uint8Array;
|
|
2
|
+
// the network layer base64-encodes at the wire boundary). Used to key in-memory maps and to serialize
|
|
3
|
+
// raw key bytes in device-state JSON.
|
|
4
|
+
/** Encode bytes as a lowercase hex string. */
|
|
5
|
+
export function toHex(b) {
|
|
6
|
+
let s = "";
|
|
7
|
+
for (const x of b)
|
|
8
|
+
s += x.toString(16).padStart(2, "0");
|
|
9
|
+
return s;
|
|
10
|
+
}
|
|
11
|
+
/** Decode a lowercase/uppercase hex string back to bytes. */
|
|
12
|
+
export function fromHex(s) {
|
|
13
|
+
const out = new Uint8Array(s.length / 2);
|
|
14
|
+
for (let i = 0; i < out.length; i++)
|
|
15
|
+
out[i] = parseInt(s.slice(i * 2, i * 2 + 2), 16);
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=hex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hex.js","sourceRoot":"","sources":["../../../src/ts-mls/hex.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,sGAAsG;AACtG,sCAAsC;AAEtC,8CAA8C;AAC9C,MAAM,UAAU,KAAK,CAAC,CAAa;IACjC,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,KAAK,MAAM,CAAC,IAAI,CAAC;QAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACxD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtF,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type TsMlsSecureChatCryptoOptions } from "./crypto.js";
|
|
2
|
+
import type { SecureChatCrypto } from "../interface.js";
|
|
3
|
+
export { TsMlsSecureChatCrypto, type TsMlsSecureChatCryptoOptions } from "./crypto.js";
|
|
4
|
+
/**
|
|
5
|
+
* Create the real ts-mls {@link SecureChatCrypto} for injection into `<SecureChatProvider crypto={…}>`.
|
|
6
|
+
*
|
|
7
|
+
* @param options - {@link TsMlsSecureChatCryptoOptions}; defaults to ciphersuite 1.
|
|
8
|
+
* @returns A ready `SecureChatCrypto` backed by ts-mls.
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { createTsMlsSecureChatCrypto } from "@agora-sdk/secure-chat-crypto/ts-mls";
|
|
12
|
+
* const crypto = createTsMlsSecureChatCrypto();
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function createTsMlsSecureChatCrypto(options?: TsMlsSecureChatCryptoOptions): SecureChatCrypto;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// @agora-sdk/secure-chat-crypto/ts-mls — the real RFC 9420 MLS core (ESM-only; pulls in ts-mls).
|
|
2
|
+
//
|
|
3
|
+
// Opt-in subpath so the heavy core is loaded ONLY by consumers that import it; the bare entry
|
|
4
|
+
// (interface) and ./testing (mock) stay dependency-free. ESM-only because ts-mls is ESM-only.
|
|
5
|
+
import { TsMlsSecureChatCrypto } from "./crypto.js";
|
|
6
|
+
export { TsMlsSecureChatCrypto } from "./crypto.js";
|
|
7
|
+
/**
|
|
8
|
+
* Create the real ts-mls {@link SecureChatCrypto} for injection into `<SecureChatProvider crypto={…}>`.
|
|
9
|
+
*
|
|
10
|
+
* @param options - {@link TsMlsSecureChatCryptoOptions}; defaults to ciphersuite 1.
|
|
11
|
+
* @returns A ready `SecureChatCrypto` backed by ts-mls.
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { createTsMlsSecureChatCrypto } from "@agora-sdk/secure-chat-crypto/ts-mls";
|
|
15
|
+
* const crypto = createTsMlsSecureChatCrypto();
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export function createTsMlsSecureChatCrypto(options) {
|
|
19
|
+
return new TsMlsSecureChatCrypto(options);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ts-mls/index.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,EAAE;AACF,8FAA8F;AAC9F,8FAA8F;AAC9F,OAAO,EAAE,qBAAqB,EAAqC,MAAM,aAAa,CAAC;AAGvF,OAAO,EAAE,qBAAqB,EAAqC,MAAM,aAAa,CAAC;AAEvF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,2BAA2B,CAAC,OAAsC;IAChF,OAAO,IAAI,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agora-sdk/secure-chat-crypto",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Agora SDK Plus, maintained by Jenova Marie",
|
|
7
|
-
"description": "The SecureChatCrypto seam for Agora end-to-end-encrypted chat (MLS / RFC 9420): the client crypto interface + a deterministic mock
|
|
7
|
+
"description": "The SecureChatCrypto seam for Agora end-to-end-encrypted chat (MLS / RFC 9420): the client crypto interface + a deterministic mock (./testing) + the real ts-mls core (./ts-mls, ESM-only). The bare entry and ./testing are dependency-free.",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"agora",
|
|
10
10
|
"secure-chat",
|
|
@@ -37,6 +37,10 @@
|
|
|
37
37
|
"types": "./dist/esm/testing.d.ts",
|
|
38
38
|
"import": "./dist/esm/testing.js",
|
|
39
39
|
"require": "./dist/cjs/testing.js"
|
|
40
|
+
},
|
|
41
|
+
"./ts-mls": {
|
|
42
|
+
"types": "./dist/esm/ts-mls/index.d.ts",
|
|
43
|
+
"import": "./dist/esm/ts-mls/index.js"
|
|
40
44
|
}
|
|
41
45
|
},
|
|
42
46
|
"publishConfig": {
|
|
@@ -45,6 +49,12 @@
|
|
|
45
49
|
"files": [
|
|
46
50
|
"dist"
|
|
47
51
|
],
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@noble/ciphers": "2.1.1",
|
|
54
|
+
"@noble/curves": "2.0.1",
|
|
55
|
+
"@noble/hashes": "2.0.1",
|
|
56
|
+
"ts-mls": "1.6.2"
|
|
57
|
+
},
|
|
48
58
|
"scripts": {
|
|
49
59
|
"build:esm": "tsc -p tsconfig.esm.json",
|
|
50
60
|
"build:cjs": "tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json",
|