@agora-sdk/secure-chat-core 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.
Files changed (67) hide show
  1. package/dist/cjs/backup/passphrase-strength.d.ts +22 -0
  2. package/dist/cjs/backup/passphrase-strength.js +75 -0
  3. package/dist/cjs/backup/passphrase-strength.js.map +1 -0
  4. package/dist/cjs/context/secure-chat-context.d.ts +12 -1
  5. package/dist/cjs/context/secure-chat-context.js +3 -1
  6. package/dist/cjs/context/secure-chat-context.js.map +1 -1
  7. package/dist/cjs/contract/index.d.ts +2 -150
  8. package/dist/cjs/contract/index.js +11 -10
  9. package/dist/cjs/contract/index.js.map +1 -1
  10. package/dist/cjs/hooks/useSecureBackup.d.ts +67 -0
  11. package/dist/cjs/hooks/useSecureBackup.js +207 -0
  12. package/dist/cjs/hooks/useSecureBackup.js.map +1 -0
  13. package/dist/cjs/hooks/useSecureDevice.d.ts +21 -1
  14. package/dist/cjs/hooks/useSecureDevice.js +46 -5
  15. package/dist/cjs/hooks/useSecureDevice.js.map +1 -1
  16. package/dist/cjs/hooks/useSecureMessages.d.ts +16 -3
  17. package/dist/cjs/hooks/useSecureMessages.js +38 -15
  18. package/dist/cjs/hooks/useSecureMessages.js.map +1 -1
  19. package/dist/cjs/hooks/useSecureSafetyNumber.d.ts +30 -0
  20. package/dist/cjs/hooks/useSecureSafetyNumber.js +82 -0
  21. package/dist/cjs/hooks/useSecureSafetyNumber.js.map +1 -0
  22. package/dist/cjs/index.d.ts +12 -1
  23. package/dist/cjs/index.js +16 -1
  24. package/dist/cjs/index.js.map +1 -1
  25. package/dist/cjs/transport/socket.d.ts +15 -3
  26. package/dist/cjs/transport/socket.js +4 -2
  27. package/dist/cjs/transport/socket.js.map +1 -1
  28. package/dist/cjs/util/padding.d.ts +39 -0
  29. package/dist/cjs/util/padding.js +80 -0
  30. package/dist/cjs/util/padding.js.map +1 -0
  31. package/dist/cjs/util/safety-number.d.ts +27 -0
  32. package/dist/cjs/util/safety-number.js +84 -0
  33. package/dist/cjs/util/safety-number.js.map +1 -0
  34. package/dist/esm/backup/passphrase-strength.d.ts +22 -0
  35. package/dist/esm/backup/passphrase-strength.js +72 -0
  36. package/dist/esm/backup/passphrase-strength.js.map +1 -0
  37. package/dist/esm/context/secure-chat-context.d.ts +12 -1
  38. package/dist/esm/context/secure-chat-context.js +3 -1
  39. package/dist/esm/context/secure-chat-context.js.map +1 -1
  40. package/dist/esm/contract/index.d.ts +2 -150
  41. package/dist/esm/contract/index.js +11 -10
  42. package/dist/esm/contract/index.js.map +1 -1
  43. package/dist/esm/hooks/useSecureBackup.d.ts +67 -0
  44. package/dist/esm/hooks/useSecureBackup.js +204 -0
  45. package/dist/esm/hooks/useSecureBackup.js.map +1 -0
  46. package/dist/esm/hooks/useSecureDevice.d.ts +21 -1
  47. package/dist/esm/hooks/useSecureDevice.js +46 -5
  48. package/dist/esm/hooks/useSecureDevice.js.map +1 -1
  49. package/dist/esm/hooks/useSecureMessages.d.ts +16 -3
  50. package/dist/esm/hooks/useSecureMessages.js +38 -15
  51. package/dist/esm/hooks/useSecureMessages.js.map +1 -1
  52. package/dist/esm/hooks/useSecureSafetyNumber.d.ts +30 -0
  53. package/dist/esm/hooks/useSecureSafetyNumber.js +79 -0
  54. package/dist/esm/hooks/useSecureSafetyNumber.js.map +1 -0
  55. package/dist/esm/index.d.ts +12 -1
  56. package/dist/esm/index.js +7 -0
  57. package/dist/esm/index.js.map +1 -1
  58. package/dist/esm/transport/socket.d.ts +15 -3
  59. package/dist/esm/transport/socket.js +4 -2
  60. package/dist/esm/transport/socket.js.map +1 -1
  61. package/dist/esm/util/padding.d.ts +39 -0
  62. package/dist/esm/util/padding.js +75 -0
  63. package/dist/esm/util/padding.js.map +1 -0
  64. package/dist/esm/util/safety-number.d.ts +27 -0
  65. package/dist/esm/util/safety-number.js +81 -0
  66. package/dist/esm/util/safety-number.js.map +1 -0
  67. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSecureBackup.js","sourceRoot":"","sources":["../../../src/hooks/useSecureBackup.tsx"],"names":[],"mappings":"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"}
@@ -8,7 +8,20 @@ export interface UseSecureDeviceOptions {
8
8
  ciphersuite?: number;
9
9
  /** How many KeyPackages to publish on registration and replenish toward. Default 20. */
10
10
  keyPackageTarget?: number;
11
- /** Auto-replenish when `secure:key-packages-low` fires. Default true. */
11
+ /**
12
+ * Low-water mark: when the server's available count drops **below** this, a top-up refills to
13
+ * {@link UseSecureDeviceOptions.keyPackageTarget}. KeyPackages are single-use, so this guards
14
+ * against exhaustion (peers unable to add this device). Default `ceil(keyPackageTarget / 2)` (10 for
15
+ * the default target of 20). Only governs the proactive/manual path — the server's
16
+ * `secure:key-packages-low` signal always tops up, since the server already judged the stock low.
17
+ */
18
+ keyPackageLowWater?: number;
19
+ /**
20
+ * Auto-replenish without app involvement. Default true. When true the hook subscribes to
21
+ * `secure:key-packages-low` and runs a one-shot proactive count check once the device is ready. When
22
+ * false, both automatic paths are disabled but {@link UseSecureDeviceValues.checkAndReplenish}
23
+ * still works on demand.
24
+ */
12
25
  autoReplenish?: boolean;
13
26
  }
14
27
  /** The state and actions returned by {@link useSecureDevice}. */
@@ -29,6 +42,13 @@ export interface UseSecureDeviceValues {
29
42
  publishKeyPackages: (count?: number) => Promise<number>;
30
43
  /** Re-query the server for the available KeyPackage count and update `keyPackagesAvailable`. */
31
44
  refreshKeyPackageCount: () => Promise<number>;
45
+ /**
46
+ * Refresh the server count and, if it's below the low-water mark, top up to `keyPackageTarget`
47
+ * (publishing only the deficit). Safe to call before {@link UseSecureDeviceValues.register} — it
48
+ * no-ops to 0 when there's no device and never throws for that case — so an app can wire it to a
49
+ * window-focus / app-foreground handler.
50
+ */
51
+ checkAndReplenish: () => Promise<number>;
32
52
  }
33
53
  /**
34
54
  * Register this client as an MLS device, persist its identity, and keep KeyPackages stocked.
@@ -4,7 +4,14 @@
4
4
  //
5
5
  // On mount it re-hydrates a persisted device (stable deviceId + private state via
6
6
  // crypto.importDeviceState) so a reload does NOT mint a new identity. register() generates, registers
7
- // on the server, and persists. Replenishes on the `secure:key-packages-low` realtime signal.
7
+ // on the server, and persists.
8
+ //
9
+ // KeyPackages are single-use (the server consumes one per group-add), so running dry means peers can't
10
+ // add this device. The hook keeps the stock topped up to `keyPackageTarget` from three triggers: the
11
+ // server's `secure:key-packages-low` realtime signal, a one-shot proactive count check once the device
12
+ // is ready (self-heals a client that missed the signal while offline), and an app-callable
13
+ // `checkAndReplenish()` (e.g. on window focus). Each top-up publishes only the DEFICIT to the target
14
+ // (using the actual available count), not a blind full batch.
8
15
  Object.defineProperty(exports, "__esModule", { value: true });
9
16
  exports.useSecureDevice = useSecureDevice;
10
17
  const react_1 = require("react");
@@ -40,6 +47,7 @@ function newDeviceId() {
40
47
  function useSecureDevice(options = {}) {
41
48
  const { crypto, rest, socket, repo } = (0, secure_chat_context_js_1.useSecureChat)();
42
49
  const { ciphersuite, keyPackageTarget = 20, autoReplenish = true } = options;
50
+ const keyPackageLowWater = options.keyPackageLowWater ?? Math.ceil(keyPackageTarget / 2);
43
51
  const [device, setDevice] = (0, react_1.useState)(null);
44
52
  const [loading, setLoading] = (0, react_1.useState)(true);
45
53
  const [registering, setRegistering] = (0, react_1.useState)(false);
@@ -47,6 +55,8 @@ function useSecureDevice(options = {}) {
47
55
  const [keyPackagesAvailable, setKeyPackagesAvailable] = (0, react_1.useState)(null);
48
56
  const deviceIdRef = (0, react_1.useRef)(options.deviceId ?? newDeviceId());
49
57
  const registerStartedRef = (0, react_1.useRef)(false);
58
+ // Guards the one-shot proactive count check so it runs once per device-ready, not on every render.
59
+ const proactiveCheckedRef = (0, react_1.useRef)(false);
50
60
  // On mount: re-hydrate a persisted device (stable id + private state). No persisted device ⇒
51
61
  // first-run; the app calls register().
52
62
  (0, react_1.useEffect)(() => {
@@ -99,6 +109,25 @@ function useSecureDevice(options = {}) {
99
109
  setKeyPackagesAvailable(available);
100
110
  return available;
101
111
  }, [rest, device]);
112
+ // Publish only the shortfall (target − available) to refill to the target; nothing if already
113
+ // at/above it. Optimistically bumps the local count so the UI reflects the refill without a re-query.
114
+ // Callers guarantee `device` exists (publishKeyPackages throws otherwise).
115
+ const replenishToTarget = (0, react_1.useCallback)(async (available) => {
116
+ const deficit = keyPackageTarget - available;
117
+ if (deficit <= 0)
118
+ return 0;
119
+ const published = await publishKeyPackages(deficit);
120
+ setKeyPackagesAvailable(available + published);
121
+ return published;
122
+ }, [keyPackageTarget, publishKeyPackages]);
123
+ const checkAndReplenish = (0, react_1.useCallback)(async () => {
124
+ if (!device)
125
+ return 0; // not registered yet — no-op (app may call this eagerly on focus)
126
+ const available = await refreshKeyPackageCount();
127
+ if (available >= keyPackageLowWater)
128
+ return 0;
129
+ return replenishToTarget(available);
130
+ }, [device, refreshKeyPackageCount, keyPackageLowWater, replenishToTarget]);
102
131
  const register = (0, react_1.useCallback)(async () => {
103
132
  registerStartedRef.current = true;
104
133
  setRegistering(true);
@@ -128,17 +157,28 @@ function useSecureDevice(options = {}) {
128
157
  setRegistering(false);
129
158
  }
130
159
  }, [crypto, rest, repo, ciphersuite]);
131
- // Auto-replenish on the server's low-water signal for this device.
160
+ // Auto-replenish on the server's low-water signal for this device. We top up to the target using the
161
+ // count the signal reports (not a blind full batch), and trust the server's "low" verdict — the
162
+ // client `keyPackageLowWater` only gates the proactive path below.
132
163
  (0, react_1.useEffect)(() => {
133
164
  if (!autoReplenish || !device)
134
165
  return;
135
166
  const off = socket.on("secure:key-packages-low", (signal) => {
136
167
  if (signal.deviceId !== device.id)
137
- return;
138
- publishKeyPackages().catch(setError);
168
+ return; // device.id is the server ROW id, not the deviceId
169
+ setKeyPackagesAvailable(signal.available);
170
+ replenishToTarget(signal.available).catch(setError);
139
171
  });
140
172
  return off;
141
- }, [autoReplenish, device, socket, publishKeyPackages]);
173
+ }, [autoReplenish, device, socket, replenishToTarget]);
174
+ // One-shot proactive top-up once the device is ready (covers both register and rehydrate-on-mount),
175
+ // so a client that missed the realtime signal while offline self-heals on next load.
176
+ (0, react_1.useEffect)(() => {
177
+ if (!autoReplenish || !device || proactiveCheckedRef.current)
178
+ return;
179
+ proactiveCheckedRef.current = true;
180
+ checkAndReplenish().catch(setError);
181
+ }, [autoReplenish, device, checkAndReplenish]);
142
182
  return {
143
183
  device,
144
184
  loading,
@@ -148,6 +188,7 @@ function useSecureDevice(options = {}) {
148
188
  register,
149
189
  publishKeyPackages,
150
190
  refreshKeyPackageCount,
191
+ checkAndReplenish,
151
192
  };
152
193
  }
153
194
  //# sourceMappingURL=useSecureDevice.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSecureDevice.js","sourceRoot":"","sources":["../../../src/hooks/useSecureDevice.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useSecureDevice.js","sourceRoot":"","sources":["../../../src/hooks/useSecureDevice.tsx"],"names":[],"mappings":"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"}
@@ -1,11 +1,24 @@
1
1
  import { SecureMessageModel } from "../contract/index.js";
2
- import { GroupHandle } from "@agora-sdk/secure-chat-crypto";
3
- /** A stored message paired with its decrypted text (when a group handle is available). */
2
+ import { GroupHandle, type SecureDecryptFailureReason } from "@agora-sdk/secure-chat-crypto";
3
+ /**
4
+ * Decryption outcome for a stored message:
5
+ * - `ok` — decrypted + authenticated; `plaintext` is set.
6
+ * - `pending` — not decryptable yet (no group handle, or the message's epoch is ahead of ours); it will
7
+ * be retried when the group advances. `plaintext` is null.
8
+ * - `rejected` — fails closed: the MLS core rejected it (replay, over-window gap, bad auth, malformed,
9
+ * too-old epoch). NEVER retried; `plaintext` is null and `rejectedReason` says why.
10
+ */
11
+ export type SecureMessageStatus = "ok" | "pending" | "rejected";
12
+ /** A stored message paired with its decryption outcome. */
4
13
  export interface DecryptedSecureMessage {
5
14
  /** The raw message row from the server (still holds the base64 ciphertext). */
6
15
  model: SecureMessageModel;
7
- /** Decrypted text, or null when no group handle is available or decryption is pending/failed. */
16
+ /** Decrypted text, or null when {@link DecryptedSecureMessage.status} is `pending` or `rejected`. */
8
17
  plaintext: string | null;
18
+ /** Decryption outcome — drives fail-closed handling and what the UI renders. */
19
+ status: SecureMessageStatus;
20
+ /** When `status` is `rejected`, why the MLS core refused the message. */
21
+ rejectedReason?: SecureDecryptFailureReason;
9
22
  }
10
23
  /** Options for {@link useSecureMessages}. */
11
24
  export interface UseSecureMessagesOptions {
@@ -8,7 +8,9 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.useSecureMessages = useSecureMessages;
10
10
  const react_1 = require("react");
11
+ const secure_chat_crypto_1 = require("@agora-sdk/secure-chat-crypto");
11
12
  const base64_js_1 = require("../util/base64.js");
13
+ const padding_js_1 = require("../util/padding.js");
12
14
  const secure_chat_context_js_1 = require("../context/secure-chat-context.js");
13
15
  /**
14
16
  * Load, decrypt, send, and live-receive messages in one secure conversation.
@@ -28,7 +30,7 @@ const secure_chat_context_js_1 = require("../context/secure-chat-context.js");
28
30
  * ```
29
31
  */
30
32
  function useSecureMessages(conversationId, options = {}) {
31
- const { rest, crypto, socket, repo, resolveGroup, getGroupVersion, subscribeGroupChange } = (0, secure_chat_context_js_1.useSecureChat)();
33
+ const { rest, crypto, socket, repo, resolveGroup, getGroupVersion, subscribeGroupChange, padding } = (0, secure_chat_context_js_1.useSecureChat)();
32
34
  const [messages, setMessages] = (0, react_1.useState)([]);
33
35
  const [before, setBefore] = (0, react_1.useState)(undefined);
34
36
  const [hasMore, setHasMore] = (0, react_1.useState)(true);
@@ -95,15 +97,34 @@ function useSecureMessages(conversationId, options = {}) {
95
97
  };
96
98
  }, [options.senderDeviceId, repo]);
97
99
  const decrypt = (0, react_1.useCallback)(async (model) => {
100
+ // No handle yet (still resolving) → retryable once it arrives.
98
101
  if (!group)
99
- return { model, plaintext: null };
102
+ return { model, plaintext: null, status: "pending" };
103
+ let plaintext;
100
104
  try {
101
- const { plaintext } = await crypto.decryptMessage(group, (0, base64_js_1.fromBase64)(model.ciphertext));
102
- return { model, plaintext: (0, base64_js_1.bytesToUtf8)(plaintext) };
105
+ ({ plaintext } = await crypto.decryptMessage(group, (0, base64_js_1.fromBase64)(model.ciphertext)));
106
+ }
107
+ catch (err) {
108
+ // Classify, don't conflate. A message from an epoch we HAVEN'T reached yet is legitimately
109
+ // buffered (a future Commit will advance us, then this re-decrypts). Anything else that fails
110
+ // at an epoch we HAVE reached is a terminal rejection — the MLS core refused it (replay,
111
+ // over-window gap, bad auth, malformed, too-old epoch). Fail closed: never show it as text and
112
+ // never silently retry it forever (the old behavior masked replays/forgeries as "pending").
113
+ if (BigInt(model.epoch) > group.epoch) {
114
+ return { model, plaintext: null, status: "pending" };
115
+ }
116
+ const rejectedReason = err instanceof secure_chat_crypto_1.SecureChatDecryptError ? err.reason : "unknown";
117
+ return { model, plaintext: null, status: "rejected", rejectedReason };
118
+ }
119
+ // Decrypt + MLS authentication succeeded, so the bytes are from a real group member. Strip the
120
+ // size-bucket padding frame (see util/padding). A bad frame here is NOT a decrypt failure — it's a
121
+ // framing/version mismatch from an authenticated sender — so fail closed as "malformed" rather
122
+ // than rendering raw padded bytes as text.
123
+ try {
124
+ return { model, plaintext: (0, base64_js_1.bytesToUtf8)((0, padding_js_1.unpadPlaintext)(plaintext)), status: "ok" };
103
125
  }
104
126
  catch {
105
- // Buffer/skip: epoch not yet reached, or undecryptable. Surface ciphertext without text.
106
- return { model, plaintext: null };
127
+ return { model, plaintext: null, status: "rejected", rejectedReason: "malformed" };
107
128
  }
108
129
  }, [crypto, group]);
109
130
  const load = (0, react_1.useCallback)(async (reset) => {
@@ -145,30 +166,32 @@ function useSecureMessages(conversationId, options = {}) {
145
166
  throw new Error("Cannot send: no MLS group handle for this conversation.");
146
167
  if (!senderDeviceId)
147
168
  throw new Error("Cannot send: senderDeviceId is required.");
148
- const { ciphertext, epoch } = await crypto.encryptMessage(group, (0, base64_js_1.utf8ToBytes)(text));
169
+ // Pad the plaintext to a size bucket BEFORE encryption so the ciphertext length leaks less
170
+ // (the receiver strips the frame in `decrypt`). See util/padding for the framing.
171
+ const { ciphertext, epoch } = await crypto.encryptMessage(group, (0, padding_js_1.padPlaintext)((0, base64_js_1.utf8ToBytes)(text), padding));
149
172
  const sent = await rest.sendMessage(conversationId, {
150
173
  ciphertext: (0, base64_js_1.toBase64)(ciphertext),
151
174
  epoch: epoch.toString(),
152
175
  senderDeviceId,
153
176
  });
154
177
  // Optimistic: we know our own plaintext without a round-trip through decrypt.
155
- setMessages((prev) => [{ model: sent, plaintext: text }, ...prev]);
156
- }, [crypto, rest, conversationId, group, senderDeviceId]);
178
+ setMessages((prev) => [{ model: sent, plaintext: text, status: "ok" }, ...prev]);
179
+ }, [crypto, rest, conversationId, group, senderDeviceId, padding]);
157
180
  (0, react_1.useEffect)(() => {
158
181
  refresh();
159
182
  // eslint-disable-next-line react-hooks/exhaustive-deps
160
183
  }, [conversationId]);
161
- // Decrypt history that was listed before the group handle resolved. On reload, the first page loads
162
- // while resolveGroup is still in flight, so those rows come back `plaintext: null`; once the handle
163
- // arrives (decrypt is recreated with it), re-decrypt the still-undecrypted rows in place no
164
- // re-fetch, scroll/pagination preserved.
184
+ // Re-decrypt buffered rows when the group handle advances. On reload the first page loads while
185
+ // resolveGroup is still in flight (those rows come back `pending`); a Commit/join also advances the
186
+ // epoch, letting previously-ahead rows decrypt. Retry ONLY `pending` rows never `rejected` ones, so
187
+ // a replay/forgery the core already refused isn't retried on every epoch bump. `ok` rows are kept.
165
188
  (0, react_1.useEffect)(() => {
166
189
  if (!group)
167
190
  return;
168
- if (!messagesRef.current.some((m) => m.plaintext === null))
191
+ if (!messagesRef.current.some((m) => m.status === "pending"))
169
192
  return;
170
193
  let alive = true;
171
- Promise.all(messagesRef.current.map((m) => (m.plaintext === null ? decrypt(m.model) : Promise.resolve(m)))).then((next) => {
194
+ Promise.all(messagesRef.current.map((m) => (m.status === "pending" ? decrypt(m.model) : Promise.resolve(m)))).then((next) => {
172
195
  if (alive)
173
196
  setMessages(next);
174
197
  });
@@ -1 +1 @@
1
- {"version":3,"file":"useSecureMessages.js","sourceRoot":"","sources":["../../../src/hooks/useSecureMessages.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useSecureMessages.js","sourceRoot":"","sources":["../../../src/hooks/useSecureMessages.tsx"],"names":[],"mappings":";AAAA,+FAA+F;AAC/F,EAAE;AACF,mGAAmG;AACnG,oGAAoG;AACpG,6FAA6F;AAC7F,6CAA6C;;AA8E7C,8CAyMC;AArRD,iCAAiE;AAEjE,sEAIuC;AACvC,iDAAmF;AACnF,mDAAkE;AAClE,8EAAkE;AAkDlE;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,iBAAiB,CAC/B,cAAsB,EACtB,UAAoC,EAAE;IAEtC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,OAAO,EAAE,GAChG,IAAA,sCAAa,GAAE,CAAC;IAElB,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,IAAA,gBAAQ,EAA2B,EAAE,CAAC,CAAC;IACvE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAqB,SAAS,CAAC,CAAC;IACpE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAU,IAAI,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAqB,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;IAC9E,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,IAAA,gBAAQ,EAAqB,OAAO,CAAC,cAAc,CAAC,CAAC;IAEjG,gGAAgG;IAChG,qGAAqG;IACrG,mEAAmE;IACnE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,IAAA,gBAAQ,EAAC,CAAC,CAAC,CAAC;IAEpD,8FAA8F;IAC9F,wDAAwD;IACxD,MAAM,WAAW,GAAG,IAAA,cAAM,EAA2B,QAAQ,CAAC,CAAC;IAC/D,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;IAE/B,kGAAkG;IAClG,iGAAiG;IACjG,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,OAAO,oBAAoB,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC,EAAE,CAAC,oBAAoB,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC,CAAC;IAE5D,qEAAqE;IACrE,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACxB,OAAO;QACT,CAAC;QACD,8FAA8F;QAC9F,wFAAwF;QACxF,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,YAAY,CAAC,cAAc,CAAC;aACzB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,KAAK;gBAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,IAAI,KAAK;gBAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC,CAAC;QACF,8FAA8F;IAChG,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;IAEhE,8EAA8E;IAC9E,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;YAC3B,iBAAiB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;YAC1C,OAAO;QACT,CAAC;QACD,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,IAAI;aACD,UAAU,EAAE;aACZ,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YACV,IAAI,KAAK;gBAAE,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,SAAS,CAAC,CAAC;QAC3D,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,IAAI,KAAK;gBAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QACL,OAAO,GAAG,EAAE;YACV,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;IAEnC,MAAM,OAAO,GAAG,IAAA,mBAAW,EACzB,KAAK,EAAE,KAAyB,EAAmC,EAAE;QACnE,+DAA+D;QAC/D,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QACjE,IAAI,SAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,CAAC,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,IAAA,sBAAU,EAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACrF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,2FAA2F;YAC3F,8FAA8F;YAC9F,yFAAyF;YACzF,+FAA+F;YAC/F,4FAA4F;YAC5F,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;gBACtC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YACvD,CAAC;YACD,MAAM,cAAc,GAClB,GAAG,YAAY,2CAAsB,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;YACjE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;QACxE,CAAC;QACD,+FAA+F;QAC/F,mGAAmG;QACnG,+FAA+F;QAC/F,2CAA2C;QAC3C,IAAI,CAAC;YACH,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAA,uBAAW,EAAC,IAAA,2BAAc,EAAC,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACpF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC;QACrF,CAAC;IACH,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IAEF,MAAM,IAAI,GAAG,IAAA,mBAAW,EACtB,KAAK,EAAE,KAAc,EAAE,EAAE;QACvB,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE;gBACnD,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;gBAClC,KAAK,EAAE,EAAE;aACV,CAAC,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YAChE,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACvD,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC9C,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzB,8DAA8D;YAC9D,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QACvE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,UAAU,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC,EACD,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CACxC,CAAC;IAEF,MAAM,OAAO,GAAG,IAAA,mBAAW,EAAC,KAAK,IAAI,EAAE;QACrC,SAAS,CAAC,SAAS,CAAC,CAAC;QACrB,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,QAAQ,GAAG,IAAA,mBAAW,EAAC,KAAK,IAAI,EAAE;QACtC,IAAI,CAAC,OAAO,IAAI,OAAO;YAAE,OAAO;QAChC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAE7B,MAAM,WAAW,GAAG,IAAA,mBAAW,EAC7B,KAAK,EAAE,IAAY,EAAiB,EAAE;QACpC,0FAA0F;QAC1F,4FAA4F;QAC5F,uFAAuF;QACvF,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QACvF,IAAI,CAAC,cAAc;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QACjF,2FAA2F;QAC3F,kFAAkF;QAClF,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CACvD,KAAK,EACL,IAAA,yBAAY,EAAC,IAAA,uBAAW,EAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CACzC,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;YAClD,UAAU,EAAE,IAAA,oBAAQ,EAAC,UAAU,CAAC;YAChC,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE;YACvB,cAAc;SACf,CAAC,CAAC;QACH,8EAA8E;QAC9E,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;IACnF,CAAC,EACD,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC,CAC/D,CAAC;IAEF,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,OAAO,EAAE,CAAC;QACV,uDAAuD;IACzD,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;IAErB,gGAAgG;IAChG,oGAAoG;IACpG,sGAAsG;IACtG,mGAAmG;IACnG,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC;YAAE,OAAO;QACrE,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,OAAO,CAAC,GAAG,CACT,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CACjG,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;YACd,IAAI,KAAK;gBAAE,WAAW,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,KAAK,GAAG,KAAK,CAAC;QAChB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IAErB,2EAA2E;IAC3E,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE;YAChD,IAAI,KAAK,CAAC,cAAc,KAAK,cAAc;gBAAE,OAAO;YACpD,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACxB,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAC3F,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;IAEtC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;AAC/E,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { type SafetyNumber } from "../util/safety-number.js";
2
+ /** The state and actions returned by {@link useSecureSafetyNumber}. */
3
+ export interface UseSecureSafetyNumberValues {
4
+ /** The derived safety number, or `null` until ready / when the conversation is not a resolvable DM. */
5
+ safetyNumber: SafetyNumber | null;
6
+ /** True while the number is being (re)computed. */
7
+ loading: boolean;
8
+ /** The last error from resolving the roster or computing, or `null`. */
9
+ error: unknown;
10
+ /** Force a recompute (e.g. after the user re-verifies). */
11
+ refresh: () => void;
12
+ }
13
+ /**
14
+ * Compute the out-of-band key-verification safety number for a direct-message conversation.
15
+ *
16
+ * Resolves the conversation's MLS group, reads its two members' public signature keys, and derives a
17
+ * symmetric {@link SafetyNumber}. Recomputes when the conversation's group handle advances (e.g. a
18
+ * processed Commit changes the roster). Returns `safetyNumber: null` when the group is unresolved or is
19
+ * not a 2-member DM.
20
+ *
21
+ * @param conversationId - The conversation to compute the safety number for.
22
+ * @returns {@link UseSecureSafetyNumberValues}.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * const { safetyNumber } = useSecureSafetyNumber(conversationId);
27
+ * // render safetyNumber?.groups for the user to compare with their peer
28
+ * ```
29
+ */
30
+ export declare function useSecureSafetyNumber(conversationId: string): UseSecureSafetyNumberValues;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ // useSecureSafetyNumber — derive the key-verification safety number for a DM conversation.
3
+ //
4
+ // Where it sits in the blind-server model: the server is untrusted and could swap a peer's KeyPackage
5
+ // (active MITM on a TOFU system). This hook reads the two devices' PUBLIC identity keys from the local
6
+ // MLS roster (crypto.exportGroupIdentities) and computes a symmetric, human-comparable safety number
7
+ // (see util/safety-number) the two users confirm out-of-band. Headless: the styled UI lives in the app
8
+ // / demo. DM-focused — for anything other than a 2-member group it returns null rather than guess.
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.useSecureSafetyNumber = useSecureSafetyNumber;
11
+ const react_1 = require("react");
12
+ const safety_number_js_1 = require("../util/safety-number.js");
13
+ const secure_chat_context_js_1 = require("../context/secure-chat-context.js");
14
+ /**
15
+ * Compute the out-of-band key-verification safety number for a direct-message conversation.
16
+ *
17
+ * Resolves the conversation's MLS group, reads its two members' public signature keys, and derives a
18
+ * symmetric {@link SafetyNumber}. Recomputes when the conversation's group handle advances (e.g. a
19
+ * processed Commit changes the roster). Returns `safetyNumber: null` when the group is unresolved or is
20
+ * not a 2-member DM.
21
+ *
22
+ * @param conversationId - The conversation to compute the safety number for.
23
+ * @returns {@link UseSecureSafetyNumberValues}.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * const { safetyNumber } = useSecureSafetyNumber(conversationId);
28
+ * // render safetyNumber?.groups for the user to compare with their peer
29
+ * ```
30
+ */
31
+ function useSecureSafetyNumber(conversationId) {
32
+ const { crypto, repo, resolveGroup, getGroupVersion, subscribeGroupChange } = (0, secure_chat_context_js_1.useSecureChat)();
33
+ const [safetyNumber, setSafetyNumber] = (0, react_1.useState)(null);
34
+ const [loading, setLoading] = (0, react_1.useState)(true);
35
+ const [error, setError] = (0, react_1.useState)(null);
36
+ const [tick, setTick] = (0, react_1.useState)(0);
37
+ // Recompute when this conversation's group handle advances (a roster change), without diffing handles.
38
+ const [groupVersion, setGroupVersion] = (0, react_1.useState)(0);
39
+ (0, react_1.useEffect)(() => {
40
+ return subscribeGroupChange(() => setGroupVersion(getGroupVersion(conversationId)));
41
+ }, [subscribeGroupChange, getGroupVersion, conversationId]);
42
+ const refresh = (0, react_1.useCallback)(() => setTick((t) => t + 1), []);
43
+ // Guards the per-run state writes against an out-of-date async resolve (conversation switch / unmount).
44
+ const runIdRef = (0, react_1.useRef)(0);
45
+ (0, react_1.useEffect)(() => {
46
+ const runId = ++runIdRef.current;
47
+ setLoading(true);
48
+ setError(null);
49
+ (async () => {
50
+ const group = await resolveGroup(conversationId);
51
+ if (!group)
52
+ return null;
53
+ const [persisted, members] = await Promise.all([
54
+ repo.loadDevice(),
55
+ crypto.exportGroupIdentities(group),
56
+ ]);
57
+ // DM only: need exactly the local device + one peer. Anything else → no safety number.
58
+ if (members.length !== 2 || !persisted)
59
+ return null;
60
+ const local = members.find((m) => m.deviceId === persisted.deviceId);
61
+ const remote = members.find((m) => m.deviceId !== persisted.deviceId);
62
+ if (!local || !remote)
63
+ return null;
64
+ return (0, safety_number_js_1.computeSafetyNumber)(local, remote);
65
+ })()
66
+ .then((sn) => {
67
+ if (runIdRef.current === runId) {
68
+ setSafetyNumber(sn);
69
+ setLoading(false);
70
+ }
71
+ })
72
+ .catch((err) => {
73
+ if (runIdRef.current === runId) {
74
+ setError(err);
75
+ setSafetyNumber(null);
76
+ setLoading(false);
77
+ }
78
+ });
79
+ }, [crypto, repo, resolveGroup, conversationId, groupVersion, tick]);
80
+ return { safetyNumber, loading, error, refresh };
81
+ }
82
+ //# sourceMappingURL=useSecureSafetyNumber.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSecureSafetyNumber.js","sourceRoot":"","sources":["../../../src/hooks/useSecureSafetyNumber.tsx"],"names":[],"mappings":";AAAA,2FAA2F;AAC3F,EAAE;AACF,sGAAsG;AACtG,uGAAuG;AACvG,qGAAqG;AACrG,uGAAuG;AACvG,mGAAmG;;AAmCnG,sDAqDC;AAtFD,iCAAiE;AACjE,+DAAkF;AAClF,8EAAkE;AAclE;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,qBAAqB,CAAC,cAAsB;IAC1D,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,GAAG,IAAA,sCAAa,GAAE,CAAC;IAE9F,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,IAAA,gBAAQ,EAAsB,IAAI,CAAC,CAAC;IAC5E,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAU,IAAI,CAAC,CAAC;IAClD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,IAAA,gBAAQ,EAAC,CAAC,CAAC,CAAC;IAEpC,uGAAuG;IACvG,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,IAAA,gBAAQ,EAAC,CAAC,CAAC,CAAC;IACpD,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,OAAO,oBAAoB,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC,EAAE,CAAC,oBAAoB,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC,CAAC;IAE5D,MAAM,OAAO,GAAG,IAAA,mBAAW,EAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAE7D,wGAAwG;IACxG,MAAM,QAAQ,GAAG,IAAA,cAAM,EAAC,CAAC,CAAC,CAAC;IAE3B,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC;QACjC,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,CAAC,KAAK,IAAI,EAAE;YACV,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,cAAc,CAAC,CAAC;YACjD,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAC;YACxB,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAC7C,IAAI,CAAC,UAAU,EAAE;gBACjB,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC;aACpC,CAAC,CAAC;YACH,uFAAuF;YACvF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS;gBAAE,OAAO,IAAI,CAAC;YACpD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAC;YACtE,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAC;YACnC,OAAO,IAAA,sCAAmB,EAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC,CAAC,EAAE;aACD,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE;YACX,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC/B,eAAe,CAAC,EAAE,CAAC,CAAC;gBACpB,UAAU,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;QACH,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,IAAI,QAAQ,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;gBAC/B,QAAQ,CAAC,GAAG,CAAC,CAAC;gBACd,eAAe,CAAC,IAAI,CAAC,CAAC;gBACtB,UAAU,CAAC,KAAK,CAAC,CAAC;YACpB,CAAC;QACH,CAAC,CAAC,CAAC;IACP,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC;IAErE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACnD,CAAC"}
@@ -8,14 +8,25 @@ export { useSecureMessages } from "./hooks/useSecureMessages.js";
8
8
  export type { UseSecureMessagesOptions, UseSecureMessagesValues, DecryptedSecureMessage, } from "./hooks/useSecureMessages.js";
9
9
  export { useSecureHandshakes } from "./hooks/useSecureHandshakes.js";
10
10
  export type { UseSecureHandshakesOptions, UseSecureHandshakesValues, } from "./hooks/useSecureHandshakes.js";
11
+ export { useSecureBackup } from "./hooks/useSecureBackup.js";
12
+ export type { UseSecureBackupValues } from "./hooks/useSecureBackup.js";
13
+ export { useSecureSafetyNumber } from "./hooks/useSecureSafetyNumber.js";
14
+ export type { UseSecureSafetyNumberValues } from "./hooks/useSecureSafetyNumber.js";
15
+ export { estimatePassphraseStrength } from "./backup/passphrase-strength.js";
16
+ export type { PassphraseStrength } from "./backup/passphrase-strength.js";
11
17
  export { SecureChatRestClient } from "./transport/rest.js";
12
18
  export type { SecureChatRestConfig } from "./transport/rest.js";
13
19
  export { SecureChatSocketClient } from "./transport/socket.js";
14
20
  export type { SecureSocket, SecureServerEvents, SecureClientEvents, SecureChatSocketConfig, } from "./transport/socket.js";
15
- export type { SecureChatCrypto, DeviceIdentity, KeyPackageBundle, GroupHandle, TargetedWelcome, CommitResult, PassphraseBackup, } from "@agora-sdk/secure-chat-crypto";
21
+ export type { SecureChatCrypto, DeviceIdentity, KeyPackageBundle, GroupHandle, GroupMemberIdentity, TargetedWelcome, CommitResult, PassphraseBackup, SecureDecryptFailureReason, } from "@agora-sdk/secure-chat-crypto";
22
+ export { SecureChatDecryptError } from "@agora-sdk/secure-chat-crypto";
16
23
  export type * from "./contract/index.js";
17
24
  export type { SecureChatStore } from "./persistence/store.js";
18
25
  export { MemoryStore } from "./persistence/memory-store.js";
19
26
  export { SecureChatRepository } from "./persistence/repository.js";
20
27
  export type { PersistedDevice } from "./persistence/repository.js";
21
28
  export { toBase64, fromBase64, utf8ToBytes, bytesToUtf8 } from "./util/base64.js";
29
+ export { padPlaintext, unpadPlaintext, nextBucket } from "./util/padding.js";
30
+ export type { PaddingPolicy } from "./util/padding.js";
31
+ export { computeSafetyNumber } from "./util/safety-number.js";
32
+ export type { SafetyNumber } from "./util/safety-number.js";
package/dist/cjs/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  // injection of a `SecureChatCrypto`. Platform packages (@agora-sdk/secure-chat-react-js, etc.)
6
6
  // re-export this and add the concrete crypto + persistence.
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.bytesToUtf8 = exports.utf8ToBytes = exports.fromBase64 = exports.toBase64 = exports.SecureChatRepository = exports.MemoryStore = exports.SecureChatSocketClient = exports.SecureChatRestClient = exports.useSecureHandshakes = exports.useSecureMessages = exports.useSecureConversations = exports.useSecureDevice = exports.useSecureChat = exports.SecureChatProvider = void 0;
8
+ exports.computeSafetyNumber = exports.nextBucket = exports.unpadPlaintext = exports.padPlaintext = exports.bytesToUtf8 = exports.utf8ToBytes = exports.fromBase64 = exports.toBase64 = exports.SecureChatRepository = exports.MemoryStore = exports.SecureChatDecryptError = exports.SecureChatSocketClient = exports.SecureChatRestClient = exports.estimatePassphraseStrength = exports.useSecureSafetyNumber = exports.useSecureBackup = exports.useSecureHandshakes = exports.useSecureMessages = exports.useSecureConversations = exports.useSecureDevice = exports.useSecureChat = exports.SecureChatProvider = void 0;
9
9
  // ── context / provider ──────────────────────────────────────────────────────
10
10
  var secure_chat_context_js_1 = require("./context/secure-chat-context.js");
11
11
  Object.defineProperty(exports, "SecureChatProvider", { enumerable: true, get: function () { return secure_chat_context_js_1.SecureChatProvider; } });
@@ -19,11 +19,20 @@ var useSecureMessages_js_1 = require("./hooks/useSecureMessages.js");
19
19
  Object.defineProperty(exports, "useSecureMessages", { enumerable: true, get: function () { return useSecureMessages_js_1.useSecureMessages; } });
20
20
  var useSecureHandshakes_js_1 = require("./hooks/useSecureHandshakes.js");
21
21
  Object.defineProperty(exports, "useSecureHandshakes", { enumerable: true, get: function () { return useSecureHandshakes_js_1.useSecureHandshakes; } });
22
+ var useSecureBackup_js_1 = require("./hooks/useSecureBackup.js");
23
+ Object.defineProperty(exports, "useSecureBackup", { enumerable: true, get: function () { return useSecureBackup_js_1.useSecureBackup; } });
24
+ var useSecureSafetyNumber_js_1 = require("./hooks/useSecureSafetyNumber.js");
25
+ Object.defineProperty(exports, "useSecureSafetyNumber", { enumerable: true, get: function () { return useSecureSafetyNumber_js_1.useSecureSafetyNumber; } });
26
+ // ── backup (passphrase strength meter) ────────────────────────────────────────
27
+ var passphrase_strength_js_1 = require("./backup/passphrase-strength.js");
28
+ Object.defineProperty(exports, "estimatePassphraseStrength", { enumerable: true, get: function () { return passphrase_strength_js_1.estimatePassphraseStrength; } });
22
29
  // ── transport (for advanced / non-React use) ─────────────────────────────────
23
30
  var rest_js_1 = require("./transport/rest.js");
24
31
  Object.defineProperty(exports, "SecureChatRestClient", { enumerable: true, get: function () { return rest_js_1.SecureChatRestClient; } });
25
32
  var socket_js_1 = require("./transport/socket.js");
26
33
  Object.defineProperty(exports, "SecureChatSocketClient", { enumerable: true, get: function () { return socket_js_1.SecureChatSocketClient; } });
34
+ var secure_chat_crypto_1 = require("@agora-sdk/secure-chat-crypto");
35
+ Object.defineProperty(exports, "SecureChatDecryptError", { enumerable: true, get: function () { return secure_chat_crypto_1.SecureChatDecryptError; } });
27
36
  var memory_store_js_1 = require("./persistence/memory-store.js");
28
37
  Object.defineProperty(exports, "MemoryStore", { enumerable: true, get: function () { return memory_store_js_1.MemoryStore; } });
29
38
  var repository_js_1 = require("./persistence/repository.js");
@@ -34,4 +43,10 @@ Object.defineProperty(exports, "toBase64", { enumerable: true, get: function ()
34
43
  Object.defineProperty(exports, "fromBase64", { enumerable: true, get: function () { return base64_js_1.fromBase64; } });
35
44
  Object.defineProperty(exports, "utf8ToBytes", { enumerable: true, get: function () { return base64_js_1.utf8ToBytes; } });
36
45
  Object.defineProperty(exports, "bytesToUtf8", { enumerable: true, get: function () { return base64_js_1.bytesToUtf8; } });
46
+ var padding_js_1 = require("./util/padding.js");
47
+ Object.defineProperty(exports, "padPlaintext", { enumerable: true, get: function () { return padding_js_1.padPlaintext; } });
48
+ Object.defineProperty(exports, "unpadPlaintext", { enumerable: true, get: function () { return padding_js_1.unpadPlaintext; } });
49
+ Object.defineProperty(exports, "nextBucket", { enumerable: true, get: function () { return padding_js_1.nextBucket; } });
50
+ var safety_number_js_1 = require("./util/safety-number.js");
51
+ Object.defineProperty(exports, "computeSafetyNumber", { enumerable: true, get: function () { return safety_number_js_1.computeSafetyNumber; } });
37
52
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,8FAA8F;AAC9F,EAAE;AACF,6FAA6F;AAC7F,+FAA+F;AAC/F,4DAA4D;;;AAE5D,+EAA+E;AAC/E,2EAAqF;AAA5E,4HAAA,kBAAkB,OAAA;AAAE,uHAAA,aAAa,OAAA;AAM1C,gFAAgF;AAChF,iEAA6D;AAApD,qHAAA,eAAe,OAAA;AAExB,+EAA2E;AAAlE,mIAAA,sBAAsB,OAAA;AAE/B,qEAAiE;AAAxD,yHAAA,iBAAiB,OAAA;AAM1B,yEAAqE;AAA5D,6HAAA,mBAAmB,OAAA;AAM5B,gFAAgF;AAChF,+CAA2D;AAAlD,+GAAA,oBAAoB,OAAA;AAE7B,mDAA+D;AAAtD,mHAAA,sBAAsB,OAAA;AAwB/B,iEAA4D;AAAnD,8GAAA,WAAW,OAAA;AACpB,6DAAmE;AAA1D,qHAAA,oBAAoB,OAAA;AAG7B,gFAAgF;AAChF,8CAAkF;AAAzE,qGAAA,QAAQ,OAAA;AAAE,uGAAA,UAAU,OAAA;AAAE,wGAAA,WAAW,OAAA;AAAE,wGAAA,WAAW,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA,8FAA8F;AAC9F,EAAE;AACF,6FAA6F;AAC7F,+FAA+F;AAC/F,4DAA4D;;;AAE5D,+EAA+E;AAC/E,2EAAqF;AAA5E,4HAAA,kBAAkB,OAAA;AAAE,uHAAA,aAAa,OAAA;AAM1C,gFAAgF;AAChF,iEAA6D;AAApD,qHAAA,eAAe,OAAA;AAExB,+EAA2E;AAAlE,mIAAA,sBAAsB,OAAA;AAE/B,qEAAiE;AAAxD,yHAAA,iBAAiB,OAAA;AAM1B,yEAAqE;AAA5D,6HAAA,mBAAmB,OAAA;AAK5B,iEAA6D;AAApD,qHAAA,eAAe,OAAA;AAExB,6EAAyE;AAAhE,iIAAA,qBAAqB,OAAA;AAG9B,iFAAiF;AACjF,0EAA6E;AAApE,oIAAA,0BAA0B,OAAA;AAGnC,gFAAgF;AAChF,+CAA2D;AAAlD,+GAAA,oBAAoB,OAAA;AAE7B,mDAA+D;AAAtD,mHAAA,sBAAsB,OAAA;AAoB/B,oEAAuE;AAA9D,4HAAA,sBAAsB,OAAA;AAO/B,iEAA4D;AAAnD,8GAAA,WAAW,OAAA;AACpB,6DAAmE;AAA1D,qHAAA,oBAAoB,OAAA;AAG7B,gFAAgF;AAChF,8CAAkF;AAAzE,qGAAA,QAAQ,OAAA;AAAE,uGAAA,UAAU,OAAA;AAAE,wGAAA,WAAW,OAAA;AAAE,wGAAA,WAAW,OAAA;AACvD,gDAA6E;AAApE,0GAAA,YAAY,OAAA;AAAE,4GAAA,cAAc,OAAA;AAAE,wGAAA,UAAU,OAAA;AAEjD,4DAA8D;AAArD,uHAAA,mBAAmB,OAAA"}
@@ -26,10 +26,22 @@ export interface SecureServerEvents {
26
26
  userId: string;
27
27
  }) => void;
28
28
  }
29
- /** Client → server events. */
29
+ /**
30
+ * Client → server events.
31
+ *
32
+ * @remarks
33
+ * Payloads are **objects**, not bare ids — the server destructures `{ conversationId }` /
34
+ * `{ deviceId }` off the first argument (agora-server `realtime/secure-socket.ts`). Emitting a bare
35
+ * string lands as `undefined` after destructuring (and, on a `null` payload, throws server-side), so
36
+ * the join silently fails. Keep these shapes in lockstep with the server's `SecureClientToServerEvents`.
37
+ */
30
38
  export interface SecureClientEvents {
31
- "join:secure-conversation": (conversationId: string) => void;
32
- "join:secure-device": (deviceId: string) => void;
39
+ "join:secure-conversation": (payload: {
40
+ conversationId: string;
41
+ }) => void;
42
+ "join:secure-device": (payload: {
43
+ deviceId: string;
44
+ }) => void;
33
45
  }
34
46
  /** A socket.io `Socket` typed with the secure-chat event maps in both directions. */
35
47
  export type SecureSocket = Socket<SecureServerEvents, SecureClientEvents>;
@@ -46,11 +46,13 @@ class SecureChatSocketClient {
46
46
  }
47
47
  /** Join a conversation room (membership-gated server-side) to receive its broadcasts. */
48
48
  joinConversation(conversationId) {
49
- this.connect().emit("join:secure-conversation", conversationId);
49
+ // Object payload — the server destructures `{ conversationId }`; a bare string would arrive as
50
+ // `undefined` and the join would silently no-op (see SecureClientEvents).
51
+ this.connect().emit("join:secure-conversation", { conversationId });
50
52
  }
51
53
  /** Explicitly join a device room (ownership-verified). Owned devices auto-join on connect. */
52
54
  joinDevice(deviceId) {
53
- this.connect().emit("join:secure-device", deviceId);
55
+ this.connect().emit("join:secure-device", { deviceId });
54
56
  }
55
57
  /**
56
58
  * Subscribe to a server → client event, auto-connecting if needed.
@@ -1 +1 @@
1
- {"version":3,"file":"socket.js","sourceRoot":"","sources":["../../../src/transport/socket.ts"],"names":[],"mappings":";AAAA,8FAA8F;AAC9F,EAAE;AACF,iGAAiG;AACjG,kGAAkG;AAClG,8FAA8F;AAC9F,kCAAkC;;;AAElC,uDAA8C;AAqC9C;;;;GAIG;AACH,MAAa,sBAAsB;IAGjC,YAA6B,MAA8B;QAA9B,WAAM,GAAN,MAAM,CAAwB;QAFnD,WAAM,GAAwB,IAAI,CAAC;IAEmB,CAAC;IAE/D;;;;OAIG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,MAAM,EAAE,SAAS;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,GAAG,IAAA,qBAAE,EAAC,GAAG,MAAM,SAAS,EAAE;YACnC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE;YAC7C,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE;YAC3C,UAAU,EAAE,CAAC,WAAW,CAAC;YACzB,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,kGAAkG;IAClG,UAAU;QACR,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,kGAAkG;IAClG,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,yFAAyF;IACzF,gBAAgB,CAAC,cAAsB;QACrC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,0BAA0B,EAAE,cAAc,CAAC,CAAC;IAClE,CAAC;IAED,8FAA8F;IAC9F,UAAU,CAAC,QAAgB;QACzB,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,QAAQ,CAAC,CAAC;IACtD,CAAC;IAED;;;;;;OAMG;IACH,EAAE,CAAqC,KAAQ,EAAE,OAA8B;QAC7E,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QACzB,4FAA4F;QAC5F,CAAC,CAAC,EAAE,CAAC,KAAc,EAAE,OAAgB,CAAC,CAAC;QACvC,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAc,EAAE,OAAgB,CAAC,CAAC;IACvD,CAAC;CACF;AAxDD,wDAwDC"}
1
+ {"version":3,"file":"socket.js","sourceRoot":"","sources":["../../../src/transport/socket.ts"],"names":[],"mappings":";AAAA,8FAA8F;AAC9F,EAAE;AACF,iGAAiG;AACjG,kGAAkG;AAClG,8FAA8F;AAC9F,kCAAkC;;;AAElC,uDAA8C;AA6C9C;;;;GAIG;AACH,MAAa,sBAAsB;IAGjC,YAA6B,MAA8B;QAA9B,WAAM,GAAN,MAAM,CAAwB;QAFnD,WAAM,GAAwB,IAAI,CAAC;IAEmB,CAAC;IAE/D;;;;OAIG;IACH,OAAO;QACL,IAAI,IAAI,CAAC,MAAM,EAAE,SAAS;YAAE,OAAO,IAAI,CAAC,MAAM,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,GAAG,IAAA,qBAAE,EAAC,GAAG,MAAM,SAAS,EAAE;YACnC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE;YAC7C,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE;YAC3C,UAAU,EAAE,CAAC,WAAW,CAAC;YACzB,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,kGAAkG;IAClG,UAAU;QACR,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,kGAAkG;IAClG,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,yFAAyF;IACzF,gBAAgB,CAAC,cAAsB;QACrC,+FAA+F;QAC/F,0EAA0E;QAC1E,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,cAAc,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,8FAA8F;IAC9F,UAAU,CAAC,QAAgB;QACzB,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED;;;;;;OAMG;IACH,EAAE,CAAqC,KAAQ,EAAE,OAA8B;QAC7E,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QACzB,4FAA4F;QAC5F,CAAC,CAAC,EAAE,CAAC,KAAc,EAAE,OAAgB,CAAC,CAAC;QACvC,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAc,EAAE,OAAgB,CAAC,CAAC;IACvD,CAAC;CACF;AA1DD,wDA0DC"}