wowok 2.1.17 → 2.1.19

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 (97) hide show
  1. package/dist/cjs/w/call/base.js +1 -0
  2. package/dist/cjs/w/call/base.js.map +1 -1
  3. package/dist/cjs/w/call/entity.js +1 -0
  4. package/dist/cjs/w/call/entity.js.map +1 -1
  5. package/dist/cjs/w/call/passport.js +1 -0
  6. package/dist/cjs/w/call/passport.js.map +1 -1
  7. package/dist/cjs/w/call/permission.js.map +1 -1
  8. package/dist/cjs/w/call/proof.js +1 -0
  9. package/dist/cjs/w/call/proof.js.map +1 -1
  10. package/dist/cjs/w/call/util.js +1 -0
  11. package/dist/cjs/w/call/util.js.map +1 -1
  12. package/dist/cjs/w/local/account.d.ts +3 -3
  13. package/dist/cjs/w/local/account.js +102 -29
  14. package/dist/cjs/w/local/account.js.map +1 -1
  15. package/dist/cjs/w/local/index.d.ts +1 -1
  16. package/dist/cjs/w/local/index.js +15 -6
  17. package/dist/cjs/w/local/index.js.map +1 -1
  18. package/dist/cjs/w/local/local.js +10 -5
  19. package/dist/cjs/w/local/local.js.map +1 -1
  20. package/dist/cjs/w/local/wip.js +1 -0
  21. package/dist/cjs/w/local/wip.js.map +1 -1
  22. package/dist/cjs/w/messenger/crypto.js +4 -4
  23. package/dist/cjs/w/messenger/crypto.js.map +1 -1
  24. package/dist/cjs/w/messenger/messenger-api.d.ts +1 -3
  25. package/dist/cjs/w/messenger/messenger-api.js +109 -56
  26. package/dist/cjs/w/messenger/messenger-api.js.map +1 -1
  27. package/dist/cjs/w/messenger/messenger-manager.d.ts +1 -6
  28. package/dist/cjs/w/messenger/messenger-manager.js +95 -150
  29. package/dist/cjs/w/messenger/messenger-manager.js.map +1 -1
  30. package/dist/cjs/w/messenger/messenger.d.ts +90 -31
  31. package/dist/cjs/w/messenger/messenger.js +517 -443
  32. package/dist/cjs/w/messenger/messenger.js.map +1 -1
  33. package/dist/cjs/w/messenger/server.d.ts +9 -1
  34. package/dist/cjs/w/messenger/server.js +56 -5
  35. package/dist/cjs/w/messenger/server.js.map +1 -1
  36. package/dist/cjs/w/messenger/session.d.ts +60 -10
  37. package/dist/cjs/w/messenger/session.js +492 -182
  38. package/dist/cjs/w/messenger/session.js.map +1 -1
  39. package/dist/cjs/w/messenger/storage.d.ts +30 -0
  40. package/dist/cjs/w/messenger/storage.js +143 -8
  41. package/dist/cjs/w/messenger/storage.js.map +1 -1
  42. package/dist/cjs/w/messenger/types.d.ts +37 -2
  43. package/dist/cjs/w/messenger/types.js +14 -3
  44. package/dist/cjs/w/messenger/types.js.map +1 -1
  45. package/dist/cjs/w/query/object.js +1 -0
  46. package/dist/cjs/w/query/object.js.map +1 -1
  47. package/dist/cjs/w/util.js +1 -0
  48. package/dist/cjs/w/util.js.map +1 -1
  49. package/dist/esm/w/call/base.js +1 -0
  50. package/dist/esm/w/call/base.js.map +1 -1
  51. package/dist/esm/w/call/entity.js +1 -0
  52. package/dist/esm/w/call/entity.js.map +1 -1
  53. package/dist/esm/w/call/passport.js +1 -0
  54. package/dist/esm/w/call/passport.js.map +1 -1
  55. package/dist/esm/w/call/permission.js.map +1 -1
  56. package/dist/esm/w/call/proof.js +1 -0
  57. package/dist/esm/w/call/proof.js.map +1 -1
  58. package/dist/esm/w/call/util.js +1 -0
  59. package/dist/esm/w/call/util.js.map +1 -1
  60. package/dist/esm/w/local/account.d.ts +3 -3
  61. package/dist/esm/w/local/account.js +102 -29
  62. package/dist/esm/w/local/account.js.map +1 -1
  63. package/dist/esm/w/local/index.d.ts +1 -1
  64. package/dist/esm/w/local/index.js +15 -6
  65. package/dist/esm/w/local/index.js.map +1 -1
  66. package/dist/esm/w/local/local.js +10 -5
  67. package/dist/esm/w/local/local.js.map +1 -1
  68. package/dist/esm/w/local/wip.js +1 -0
  69. package/dist/esm/w/local/wip.js.map +1 -1
  70. package/dist/esm/w/messenger/crypto.js +4 -4
  71. package/dist/esm/w/messenger/crypto.js.map +1 -1
  72. package/dist/esm/w/messenger/messenger-api.d.ts +1 -3
  73. package/dist/esm/w/messenger/messenger-api.js +109 -56
  74. package/dist/esm/w/messenger/messenger-api.js.map +1 -1
  75. package/dist/esm/w/messenger/messenger-manager.d.ts +1 -6
  76. package/dist/esm/w/messenger/messenger-manager.js +95 -150
  77. package/dist/esm/w/messenger/messenger-manager.js.map +1 -1
  78. package/dist/esm/w/messenger/messenger.d.ts +90 -31
  79. package/dist/esm/w/messenger/messenger.js +517 -443
  80. package/dist/esm/w/messenger/messenger.js.map +1 -1
  81. package/dist/esm/w/messenger/server.d.ts +9 -1
  82. package/dist/esm/w/messenger/server.js +56 -5
  83. package/dist/esm/w/messenger/server.js.map +1 -1
  84. package/dist/esm/w/messenger/session.d.ts +60 -10
  85. package/dist/esm/w/messenger/session.js +492 -182
  86. package/dist/esm/w/messenger/session.js.map +1 -1
  87. package/dist/esm/w/messenger/storage.d.ts +30 -0
  88. package/dist/esm/w/messenger/storage.js +143 -8
  89. package/dist/esm/w/messenger/storage.js.map +1 -1
  90. package/dist/esm/w/messenger/types.d.ts +37 -2
  91. package/dist/esm/w/messenger/types.js +14 -3
  92. package/dist/esm/w/messenger/types.js.map +1 -1
  93. package/dist/esm/w/query/object.js +1 -0
  94. package/dist/esm/w/query/object.js.map +1 -1
  95. package/dist/esm/w/util.js +1 -0
  96. package/dist/esm/w/util.js.map +1 -1
  97. package/package.json +1 -2
@@ -10,11 +10,17 @@
10
10
  * 3. 消息加密和解密
11
11
  */
12
12
  import { KeyHelper, SessionBuilder, SessionCipher, SignalProtocolAddress, } from "libsignal-protocol-typescript";
13
- import { Account } from "../local/account.js";
14
13
  import { SignalProtocolStorage } from "./storage.js";
15
14
  import { MessengerServerClient } from "./server.js";
16
15
  import { recoverXed25519FromX25519PrivateKey, arrayBufferToUint8Array, bytesToBase64, base64ToBytes, } from "./crypto.js";
17
16
  import { MessageType, DEFAULT_MESSENGER_CONFIG, MessengerError, MessengerErrorCode, DEFAULT_DEVICE_ID, } from "./types.js";
17
+ // 动态导入 Account 以避免循环依赖
18
+ // eslint-disable-next-line import/no-cycle
19
+ async function getAccount() {
20
+ // eslint-disable-next-line import/no-cycle
21
+ const { Account } = await import("../local/account.js");
22
+ return Account.Instance();
23
+ }
18
24
  export class MessengerSession {
19
25
  store;
20
26
  serverClient;
@@ -53,7 +59,7 @@ export class MessengerSession {
53
59
  throw new MessengerError(MessengerErrorCode.IDENTITY_NOT_FOUND, "userAddress is required to derive identity");
54
60
  }
55
61
  // 从 Account 派生 X25519 密钥对
56
- const { privateKey, publicKey } = await Account.Instance().deriveX25519KeyPair(userAddress);
62
+ const { privateKey, publicKey } = await (await getAccount()).deriveX25519KeyPair(userAddress);
57
63
  // 生成注册 ID(可以从公钥派生,确保确定性)
58
64
  const registrationId = this.deriveRegistrationId(publicKey);
59
65
  // 转换为 Signal Protocol 格式
@@ -62,8 +68,8 @@ export class MessengerSession {
62
68
  prefixedPublicKey[0] = 0x05; // Signal Protocol 标准前缀
63
69
  prefixedPublicKey.set(publicKey, 1);
64
70
  const signalIdentity = {
65
- privKey: privateKey.buffer.slice(privateKey.byteOffset, privateKey.byteOffset + privateKey.byteLength),
66
- pubKey: prefixedPublicKey.buffer.slice(prefixedPublicKey.byteOffset, prefixedPublicKey.byteOffset + prefixedPublicKey.byteLength),
71
+ privKey: privateKey.slice().buffer,
72
+ pubKey: prefixedPublicKey.slice().buffer,
67
73
  };
68
74
  await this.store.setIdentity(signalIdentity, registrationId);
69
75
  const xed25519 = recoverXed25519FromX25519PrivateKey(privateKey);
@@ -89,61 +95,153 @@ export class MessengerSession {
89
95
  */
90
96
  async registerDevice(userAddress) {
91
97
  const identity = await this.ensureIdentity(userAddress);
92
- // 首次注册时上传最大数量的预密钥
93
- const prekeys = await this.generatePreKeyBatch(this.config.prekey_count);
94
- // 注意:KeyHelper.generateIdentityKeyPair 返回的 identityKey 已经带有 0x05 前缀了
95
- // 不要再次 encodeX25519PublicKey,否则会有双重前缀!
98
+ const signedPreKeyId = 1;
99
+ let signedPreKey;
100
+ let signedPreKeyPublicKey;
101
+ let signedPreKeySignature;
102
+ let isNewKey = false;
103
+ // 【关键修复】使用带签名的存储方法
104
+ const existingSignedPreKey = await this.store.loadSignedPreKeyWithSignature(signedPreKeyId);
105
+ if (existingSignedPreKey) {
106
+ signedPreKeyPublicKey = arrayBufferToUint8Array(existingSignedPreKey.pubKey);
107
+ signedPreKeySignature = arrayBufferToUint8Array(existingSignedPreKey.signature);
108
+ signedPreKey = {
109
+ keyId: signedPreKeyId,
110
+ keyPair: {
111
+ pubKey: existingSignedPreKey.pubKey,
112
+ privKey: existingSignedPreKey.privKey,
113
+ },
114
+ signature: existingSignedPreKey.signature,
115
+ };
116
+ }
117
+ else {
118
+ signedPreKey = await KeyHelper.generateSignedPreKey(identity.signalIdentity, signedPreKeyId);
119
+ signedPreKeyPublicKey = arrayBufferToUint8Array(signedPreKey.keyPair.pubKey);
120
+ signedPreKeySignature = arrayBufferToUint8Array(signedPreKey.signature);
121
+ isNewKey = true;
122
+ }
123
+ // 生成 One-Time PreKeys(暂不保存)
124
+ const oneTimePrekeys = await this.generatePreKeyBatch(this.config.prekey_count, userAddress);
96
125
  const prefixedIdentityKey = arrayBufferToUint8Array(identity.signalIdentity.pubKey);
97
- // 获取账户信息用于签名
98
- const account = await Account.Instance().get(userAddress, false);
126
+ const account = await (await getAccount()).get(userAddress, false);
99
127
  if (!account?.pubkey) {
100
128
  throw new MessengerError(MessengerErrorCode.IDENTITY_NOT_FOUND, `Account not found for ${userAddress}`);
101
129
  }
102
- // 构造签名
103
130
  const timestamp = Date.now();
104
131
  const nonce = this.generateNonce();
105
132
  const message = `register:${account.pubkey}:${timestamp}:${nonce}`;
106
- const signResult = await Account.Instance().signData(userAddress, message);
133
+ const signResult = await (await getAccount()).signData(userAddress, message);
107
134
  const signature = Buffer.from(signResult.signature.slice(2), "hex");
108
135
  const registerRequest = {
109
136
  userAddress,
110
137
  deviceId: DEFAULT_DEVICE_ID,
111
138
  registrationId: identity.registrationId,
112
139
  identityKey: bytesToBase64(prefixedIdentityKey),
113
- prekeys,
140
+ signedPrekey: {
141
+ keyId: signedPreKeyId,
142
+ publicKey: bytesToBase64(signedPreKeyPublicKey),
143
+ signature: bytesToBase64(signedPreKeySignature),
144
+ },
145
+ prekeys: oneTimePrekeys,
114
146
  publicKey: account.pubkey,
115
147
  signatureScheme: "ED25519",
116
148
  signature: bytesToBase64(signature),
117
149
  timestamp,
118
150
  nonce,
119
151
  };
152
+ console.log(`[Session Debug] Sending register request to server...`);
120
153
  await this.serverClient.registerDevice(registerRequest);
154
+ console.log(`[Session Debug] Server register request successful!`);
155
+ console.log(`[Session Debug] Verifying registration complete...`);
156
+ await this.verifyRegistrationComplete(userAddress);
157
+ console.log(`[Session Debug] Registration verification complete!`);
158
+ // 【关键修复】只有是新 key 时才保存到本地数据库(包含签名)
159
+ if (isNewKey) {
160
+ await this.store.storeSignedPreKeyWithSignature(signedPreKeyId, signedPreKey.keyPair, signedPreKeySignature.buffer.slice(0));
161
+ }
121
162
  }
122
163
  /**
123
- * 生成预密钥批次
164
+ * 验证注册是否完成
165
+ * 轮询检查服务器是否已存在该用户
124
166
  */
125
- async generatePreKeyBatch(count) {
167
+ async verifyRegistrationComplete(userAddress, maxRetries = 10, retryDelay = 500) {
168
+ for (let i = 0; i < maxRetries; i++) {
169
+ try {
170
+ const status = await this.serverClient.getPrekeyStatus(userAddress);
171
+ // 如果成功获取状态,说明注册已完成
172
+ console.log(`Registration verified for ${userAddress}, prekeys: ${status.currentCount}/${status.maxAllowed}`);
173
+ return;
174
+ }
175
+ catch (error) {
176
+ // 如果是 404,说明注册还没完成,继续等待
177
+ if (error?.message?.includes("404") || error?.status === 404) {
178
+ if (i < maxRetries - 1) {
179
+ console.log(`Waiting for registration to complete... (${i + 1}/${maxRetries})`);
180
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
181
+ continue;
182
+ }
183
+ }
184
+ // 其他错误,抛出
185
+ throw error;
186
+ }
187
+ }
188
+ throw new MessengerError(MessengerErrorCode.REGISTRATION_FAILED, `Registration verification failed after ${maxRetries} attempts`);
189
+ }
190
+ /**
191
+ * 检查设备是否已在服务器上注册
192
+ * 通过查询服务器上的预密钥状态来判断
193
+ */
194
+ async isDeviceRegistered(userAddress) {
195
+ try {
196
+ // 检查本地是否有 signedPreKey(使用带签名的方法)
197
+ const signedPreKey = await this.store.loadSignedPreKeyWithSignature(1);
198
+ if (!signedPreKey) {
199
+ return false;
200
+ }
201
+ // 尝试从服务器获取预密钥状态
202
+ const _status = await this.serverClient.getPrekeyStatus(userAddress);
203
+ return true;
204
+ }
205
+ catch (error) {
206
+ // 如果是 404,说明设备未注册
207
+ if (error?.message?.includes("404") || error?.status === 404) {
208
+ return false;
209
+ }
210
+ return false;
211
+ }
212
+ }
213
+ /**
214
+ * 生成预密钥批次(One-Time PreKeys)
215
+ */
216
+ async generatePreKeyBatch(count, userAddress) {
126
217
  if (count <= 0)
127
218
  return [];
128
- const identity = await this.ensureIdentity();
129
219
  const meta = await this.store.getMeta();
130
220
  let nextPreKeyId = meta.nextPreKeyId || 1;
131
221
  const prekeys = [];
132
222
  for (let i = 0; i < count; i++) {
133
223
  const keyId = nextPreKeyId + i;
134
- // 使用双棘轮库的 KeyHelper.generateSignedPreKey 生成带 X25519 签名的 signed prekey
135
- const signedPreKey = await KeyHelper.generateSignedPreKey(identity.signalIdentity, keyId);
136
- const prekeyPublicKey = arrayBufferToUint8Array(signedPreKey.keyPair.pubKey);
137
- // 注意:KeyHelper.generateSignedPreKey 返回的 prekey 已经带有 0x05 前缀了
138
- // 不要再次 encodeX25519PublicKey,否则会有双重前缀!
139
- const prefixedPublicKey = prekeyPublicKey;
140
- // 双棘轮库已经生成了 X25519 签名,直接使用
141
- const signature = arrayBufferToUint8Array(signedPreKey.signature);
142
- await this.store.storePreKey(keyId, signedPreKey.keyPair);
143
- await this.store.storeSignedPreKey(keyId, signedPreKey.keyPair);
224
+ const existingPreKey = await this.store.loadPreKey(keyId);
225
+ if (existingPreKey) {
226
+ const pubKeyBytes = new Uint8Array(existingPreKey.pubKey);
227
+ const publicKeyBase64 = bytesToBase64(pubKeyBytes);
228
+ const signResult = await (await getAccount()).signData(userAddress, pubKeyBytes);
229
+ const signature = Buffer.from(signResult.signature.slice(2), "hex");
230
+ prekeys.push({
231
+ keyId,
232
+ publicKey: publicKeyBase64,
233
+ signature: bytesToBase64(signature),
234
+ });
235
+ continue;
236
+ }
237
+ const preKey = await KeyHelper.generatePreKey(keyId);
238
+ const pubKeyBytes = new Uint8Array(preKey.keyPair.pubKey);
239
+ const signResult = await (await getAccount()).signData(userAddress, pubKeyBytes);
240
+ const signature = Buffer.from(signResult.signature.slice(2), "hex");
241
+ await this.store.storePreKey(keyId, preKey.keyPair);
144
242
  prekeys.push({
145
243
  keyId,
146
- publicKey: bytesToBase64(prefixedPublicKey),
244
+ publicKey: bytesToBase64(pubKeyBytes),
147
245
  signature: bytesToBase64(signature),
148
246
  });
149
247
  }
@@ -153,44 +251,30 @@ export class MessengerSession {
153
251
  }
154
252
  /**
155
253
  * 确保服务器上有足够可用的预密钥
156
- *
157
- * 逻辑:查询服务器当前预密钥数量,按需生成并上传,补充到服务器最大容量
158
254
  */
159
255
  async ensurePreKeys(userAddress, force = false) {
160
- // 1. 查询服务器当前预密钥状态
161
256
  const status = await this.serverClient.getPrekeyStatus(userAddress);
162
- // 2. 如果服务器已满且非强制模式,直接返回
163
257
  if (!force && status.currentCount >= status.maxAllowed) {
164
- throw new MessengerError(MessengerErrorCode.PREKEYS_FULL, `Prekeys already full on server: ${status.currentCount}/${status.maxAllowed}`);
258
+ return;
165
259
  }
166
- // 3. 计算需要补充的数量
167
260
  const needCount = status.maxAllowed - status.currentCount;
168
261
  if (needCount <= 0) {
169
- /*console.log(
170
- `No need to refill prekeys, server has ${status.currentCount}/${status.maxAllowed}`,
171
- );*/
172
262
  return;
173
263
  }
174
- /*console.log(
175
- `Refilling prekeys: server has ${status.currentCount}/${status.maxAllowed}, need ${needCount}`,
176
- );*/
177
- // 4. 确保身份已初始化
178
264
  await this.ensureIdentity(userAddress);
179
- // 5. 生成所需数量的预密钥
180
- const prekeys = await this.generatePreKeyBatch(needCount);
181
- // 6. 获取账户信息用于签名
182
- const account = await Account.Instance().get(userAddress, false);
265
+ const prekeys = await this.generatePreKeyBatch(needCount, userAddress);
266
+ if (prekeys.length === 0) {
267
+ return;
268
+ }
269
+ const account = await (await getAccount()).get(userAddress, false);
183
270
  if (!account?.pubkey) {
184
271
  throw new MessengerError(MessengerErrorCode.IDENTITY_NOT_FOUND, `Account not found for ${userAddress}`);
185
272
  }
186
- // 7. 构造上传请求(包含签名)
187
- // 8. 生成签名
188
273
  const timestamp = Date.now();
189
274
  const nonce = this.generateNonce();
190
275
  const message = `upload_prekeys:${account.pubkey}:${timestamp}:${nonce}`;
191
- const signResult = await Account.Instance().signData(userAddress, message);
276
+ const signResult = await (await getAccount()).signData(userAddress, message);
192
277
  const signature = Buffer.from(signResult.signature.slice(2), "hex");
193
- // 9. 上传预密钥(服务器会自动丢弃超过最大数量的部分)
194
278
  await this.serverClient.uploadPreKeys({
195
279
  userAddress,
196
280
  prekeys,
@@ -212,185 +296,255 @@ export class MessengerSession {
212
296
  /**
213
297
  * 建立与对方的会话
214
298
  */
215
- async establishSession(myAddress, peerAddress, peerDeviceId = DEFAULT_DEVICE_ID) {
299
+ async establishSession(myAddress, peerAddress, peerDeviceId = DEFAULT_DEVICE_ID, remoteBundle) {
216
300
  const protocolAddress = new SignalProtocolAddress(peerAddress, peerDeviceId);
217
- // 检查是否已有会话
218
301
  const existingSession = await this.store.loadSession(protocolAddress.toString());
219
302
  if (existingSession) {
220
303
  return;
221
304
  }
222
- // 获取账户信息以生成签名
223
- const account = await Account.Instance().get(myAddress, false);
224
- if (!account?.pubkey) {
225
- throw new MessengerError(MessengerErrorCode.IDENTITY_NOT_FOUND, `Account not found for ${myAddress}`);
305
+ if (!remoteBundle) {
306
+ const account = await (await getAccount()).get(myAddress, false);
307
+ if (!account?.pubkey) {
308
+ throw new MessengerError(MessengerErrorCode.IDENTITY_NOT_FOUND, `Account not found for ${myAddress}`);
309
+ }
310
+ const timestamp = Date.now();
311
+ const nonce = this.generateNonce();
312
+ const publicKeyWithFlag = account.pubkey;
313
+ const message = `get_bundle:${myAddress}:${timestamp}:${nonce}`;
314
+ const signResult = await (await getAccount()).signData(myAddress, message);
315
+ const signature = Buffer.from(signResult.signature.slice(2), "hex");
316
+ remoteBundle = await this.serverClient.fetchRemoteBundle(peerAddress, myAddress, publicKeyWithFlag, {
317
+ signatureScheme: "ED25519",
318
+ signature: bytesToBase64(new Uint8Array(signature)),
319
+ timestamp,
320
+ nonce,
321
+ }, peerDeviceId);
226
322
  }
227
- // 构造签名
228
- const timestamp = Date.now();
229
- const nonce = this.generateNonce();
230
- const publicKeyWithFlag = account.pubkey;
231
- // 签名格式: get_bundle:{address}:{timestamp}:{nonce}
232
- const message = `get_bundle:${myAddress}:${timestamp}:${nonce}`;
233
- const signResult = await Account.Instance().signData(myAddress, message);
234
- const signature = Buffer.from(signResult.signature.slice(2), "hex");
235
- // 获取对方密钥包(带签名验证)
236
- const remoteBundle = await this.serverClient.fetchRemoteBundle(peerAddress, myAddress, publicKeyWithFlag, {
237
- signatureScheme: "ED25519",
238
- signature: bytesToBase64(new Uint8Array(signature)),
239
- timestamp,
240
- nonce,
241
- }, peerDeviceId);
242
- const preferredPreKey = remoteBundle.signedPrekey;
243
- if (!preferredPreKey) {
323
+ const oneTimePreKey = remoteBundle.oneTimePrekey;
324
+ const signedPreKey = remoteBundle.signedPrekey;
325
+ if (!signedPreKey) {
244
326
  throw new MessengerError(MessengerErrorCode.IDENTITY_NOT_FOUND, `No signed prekey available for ${peerAddress}`);
245
327
  }
246
- // 转换为 Signal Protocol 设备格式
247
328
  const identityKeyBytes = base64ToBytes(remoteBundle.identityKey);
248
- const preKeyPublicBytes = base64ToBytes(preferredPreKey.publicKey);
249
- const signatureBytes = base64ToBytes(preferredPreKey.signature);
250
- // 注意:identityKey 和 signedPreKey.publicKey 都不要 decode 去掉前缀!
251
- // 因为当初签名时用的就是带 0x05 前缀的原始公钥!
252
329
  const originalIdentityKeyWithPrefix = new Uint8Array(identityKeyBytes);
253
- const originalPreKeyWithPrefix = new Uint8Array(preKeyPublicBytes);
330
+ const signedPreKeyPublicBytes = base64ToBytes(signedPreKey.publicKey);
331
+ const signedPreKeySignatureBytes = base64ToBytes(signedPreKey.signature);
332
+ const originalSignedPreKeyWithPrefix = new Uint8Array(signedPreKeyPublicBytes);
333
+ let oneTimePreKeyData = undefined;
334
+ if (oneTimePreKey) {
335
+ const oneTimePreKeyPublicBytes = base64ToBytes(oneTimePreKey.publicKey);
336
+ const originalOneTimePreKeyWithPrefix = new Uint8Array(oneTimePreKeyPublicBytes);
337
+ oneTimePreKeyData = {
338
+ keyId: oneTimePreKey.keyId,
339
+ publicKey: originalOneTimePreKeyWithPrefix.buffer.slice(originalOneTimePreKeyWithPrefix.byteOffset, originalOneTimePreKeyWithPrefix.byteOffset +
340
+ originalOneTimePreKeyWithPrefix.byteLength),
341
+ };
342
+ }
254
343
  const device = {
255
344
  registrationId: remoteBundle.registrationId,
256
345
  identityKey: originalIdentityKeyWithPrefix.buffer.slice(originalIdentityKeyWithPrefix.byteOffset, originalIdentityKeyWithPrefix.byteOffset +
257
346
  originalIdentityKeyWithPrefix.byteLength),
258
347
  signedPreKey: {
259
- keyId: preferredPreKey.keyId,
260
- publicKey: originalPreKeyWithPrefix.buffer.slice(originalPreKeyWithPrefix.byteOffset, originalPreKeyWithPrefix.byteOffset +
261
- originalPreKeyWithPrefix.byteLength),
262
- signature: new Uint8Array(signatureBytes).buffer.slice(signatureBytes.byteOffset, signatureBytes.byteOffset + signatureBytes.byteLength),
348
+ keyId: signedPreKey.keyId,
349
+ publicKey: originalSignedPreKeyWithPrefix.buffer.slice(originalSignedPreKeyWithPrefix.byteOffset, originalSignedPreKeyWithPrefix.byteOffset +
350
+ originalSignedPreKeyWithPrefix.byteLength),
351
+ signature: new Uint8Array(signedPreKeySignatureBytes).buffer.slice(signedPreKeySignatureBytes.byteOffset, signedPreKeySignatureBytes.byteOffset +
352
+ signedPreKeySignatureBytes.byteLength),
263
353
  },
264
- // 服务器只提供 signedPreKey,没有单独的 one-time preKey
265
- // 这是可以的,Signal Protocol 支持仅使用 signedPreKey 建立会话
266
- preKey: undefined,
354
+ preKey: oneTimePreKeyData,
267
355
  };
268
- // 建立会话
269
356
  const builder = new SessionBuilder(this.store, protocolAddress);
270
357
  await builder.processPreKey(device);
271
- // 显式存储对方的身份密钥,以便后续解密对方的回复
272
- // 使用 protocolAddress.toString() 作为键(包含 deviceId)
273
358
  await this.store.saveIdentity(protocolAddress.toString(), device.identityKey);
274
359
  }
275
360
  /**
276
361
  * 加密消息
277
- * @param myAddress 发送方地址
278
- * @param peerAddress 接收方地址
279
- * @param plaintext 明文
280
- * @param peerDeviceId 设备ID
281
- * @returns 加密后的消息(type 表示底层 Signal Protocol 消息类型:3=PreKeyMessage, 1=WhisperMessage)
282
362
  */
283
363
  async encryptMessage(myAddress, peerAddress, plaintext, peerDeviceId = DEFAULT_DEVICE_ID) {
284
364
  const protocolAddress = new SignalProtocolAddress(peerAddress, peerDeviceId);
285
- // 检查是否已有会话(用于确定底层消息类型)
286
365
  const sessionKey = protocolAddress.toString();
287
- const existingSession = await this.store.loadSession(sessionKey);
288
- const isNewSession = !existingSession;
289
- // 只有在新会话时才建立会话,避免重置已存在的会话状态
290
- if (isNewSession) {
291
- await this.establishSession(myAddress, peerAddress, peerDeviceId);
292
- }
293
- const cipher = new SessionCipher(this.store, protocolAddress);
294
- const encoder = new TextEncoder();
295
- const cipherMessage = await cipher.encrypt(encoder.encode(plaintext).buffer);
296
- // Convert body to ArrayBuffer if it's a string
297
- let bodyBuffer;
298
- if (typeof cipherMessage.body === "string") {
299
- const bodyBytes = Buffer.from(cipherMessage.body, "binary");
300
- bodyBuffer = new Uint8Array(bodyBytes).buffer;
301
- }
302
- else if (cipherMessage.body) {
303
- bodyBuffer = cipherMessage.body;
304
- }
305
- else {
306
- throw new MessengerError(MessengerErrorCode.ENCRYPTION_FAILED, "Cipher message body is empty");
366
+ let existingSession = await this.store.loadSession(sessionKey);
367
+ let isNewSession = !existingSession;
368
+ let retryCount = 0;
369
+ const maxRetries = 5; // 【用户要求】加大容错窗口,让消息可以重试更多次
370
+ while (retryCount <= maxRetries) {
371
+ try {
372
+ if (isNewSession) {
373
+ console.log(`[Session] 建立新会话 (尝试 ${retryCount + 1}/${maxRetries + 1})`);
374
+ const account = await (await getAccount()).get(myAddress, false);
375
+ if (!account?.pubkey) {
376
+ throw new MessengerError(MessengerErrorCode.IDENTITY_NOT_FOUND, `Account not found for ${myAddress}`);
377
+ }
378
+ const timestamp = Date.now();
379
+ const nonce = this.generateNonce();
380
+ const publicKeyWithFlag = account.pubkey;
381
+ const message = `get_bundle:${myAddress}:${timestamp}:${nonce}`;
382
+ const signResult = await (await getAccount()).signData(myAddress, message);
383
+ const signature = Buffer.from(signResult.signature.slice(2), "hex");
384
+ const remoteBundle = await this.serverClient.fetchRemoteBundle(peerAddress, myAddress, publicKeyWithFlag, {
385
+ signatureScheme: "ED25519",
386
+ signature: bytesToBase64(new Uint8Array(signature)),
387
+ timestamp,
388
+ nonce,
389
+ }, peerDeviceId);
390
+ await this.establishSession(myAddress, peerAddress, peerDeviceId, remoteBundle);
391
+ }
392
+ const cipher = new SessionCipher(this.store, protocolAddress);
393
+ const encoder = new TextEncoder();
394
+ const cipherMessage = await cipher.encrypt(encoder.encode(plaintext).buffer);
395
+ let bodyBuffer;
396
+ if (typeof cipherMessage.body === "string") {
397
+ const bodyBytes = Buffer.from(cipherMessage.body, "binary");
398
+ bodyBuffer = new Uint8Array(bodyBytes).buffer;
399
+ }
400
+ else if (cipherMessage.body) {
401
+ bodyBuffer = cipherMessage.body;
402
+ }
403
+ else {
404
+ throw new MessengerError(MessengerErrorCode.ENCRYPTION_FAILED, "Cipher message body is empty");
405
+ }
406
+ return {
407
+ type: cipherMessage.type,
408
+ body: bodyBuffer,
409
+ registrationId: cipherMessage.registrationId,
410
+ };
411
+ }
412
+ catch (error) {
413
+ console.error(`[Session] 加密失败 (尝试 ${retryCount + 1}/${maxRetries + 1}):`, error);
414
+ if (retryCount >= maxRetries) {
415
+ throw error;
416
+ }
417
+ console.log(`[Session] 尝试删除旧会话并重新建立...`);
418
+ try {
419
+ if (existingSession) {
420
+ await this.store.removeSession(sessionKey);
421
+ existingSession = undefined;
422
+ }
423
+ isNewSession = true;
424
+ retryCount++;
425
+ await new Promise((resolve) => setTimeout(resolve, 100));
426
+ }
427
+ catch (rebuildError) {
428
+ console.error(`[Session] 重新建立会话失败:`, rebuildError);
429
+ throw error;
430
+ }
431
+ }
307
432
  }
308
- // 使用 SessionCipher 返回的消息类型(1 3)
309
- // SessionCipher 根据 session.pendingPreKey 是否存在来决定消息类型
310
- /*const msgType = cipherMessage.type === 3 ? "PREKEY" : "WHISPER";
311
- console.log(
312
- `[Session Debug] 加密完成: msgType=${msgType}(${cipherMessage.type}), bodyLength=${bodyBuffer.byteLength}, isNewSession=${isNewSession}`,
313
- );*/
314
- return {
315
- type: cipherMessage.type,
316
- body: bodyBuffer,
317
- registrationId: cipherMessage.registrationId,
318
- };
433
+ throw new MessengerError(MessengerErrorCode.ENCRYPTION_FAILED, "Encryption failed after multiple attempts");
319
434
  }
320
435
  /**
321
436
  * 解密消息
322
437
  */
323
438
  async decryptMessage(myAddress, peerAddress, ciphertext, msgType, peerDeviceId = DEFAULT_DEVICE_ID) {
324
439
  const protocolAddress = new SignalProtocolAddress(peerAddress, peerDeviceId);
325
- // Signal 协议中,接收方直接使用自己的私钥解密消息
326
- // decryptPreKeyWhisperMessage 会自动处理会话建立,不需要预先获取发送方的密钥包
327
- // 发送方使用接收方的预密钥公钥加密,接收方使用自己的预密钥私钥解密
328
- const cipher = new SessionCipher(this.store, protocolAddress);
329
- const decoder = new TextDecoder();
330
- // 检查会话状态
331
440
  const sessionKey = protocolAddress.toString();
332
- const existingSession = await this.store.loadSession(sessionKey);
333
- let plaintextBuffer;
334
- const ciphertextArray = new Uint8Array(ciphertext);
441
+ let existingSession = await this.store.loadSession(sessionKey);
442
+ const decoder = new TextDecoder();
335
443
  let ciphertextBinary = "";
444
+ const ciphertextArray = new Uint8Array(ciphertext);
336
445
  for (let i = 0; i < ciphertextArray.length; i++) {
337
446
  ciphertextBinary += String.fromCharCode(ciphertextArray[i]);
338
447
  }
339
- try {
340
- if (msgType === MessageType.PREKEY_MESSAGE) {
341
- // 【新增】如果已有会话,说明对方重置了会话,需要删除旧会话
342
- if (existingSession) {
343
- await this.store.removeSession(sessionKey);
344
- // 重新创建 cipher(使用更新后的 store)
345
- const newCipher = new SessionCipher(this.store, protocolAddress);
346
- plaintextBuffer =
347
- await newCipher.decryptPreKeyWhisperMessage(ciphertextBinary, "binary");
448
+ let retryCount = 0;
449
+ const maxRetries = 5; // 【用户要求】加大容错窗口,让消息可以重试更多次
450
+ // 【新增】如果是 WHISPER_MESSAGE 且没有现有会话,直接抛出可重试错误
451
+ if (msgType !== MessageType.PREKEY_MESSAGE && !existingSession) {
452
+ console.log(`[Session] 收到 WHISPER_MESSAGE 但无现有会话,需要等待 PREKEY_MESSAGE`);
453
+ throw new Error("收到 WHISPER_MESSAGE 但无现有会话,需要等待 PREKEY_MESSAGE");
454
+ }
455
+ while (retryCount <= maxRetries) {
456
+ try {
457
+ const cipher = new SessionCipher(this.store, protocolAddress);
458
+ let plaintextBuffer;
459
+ if (msgType === MessageType.PREKEY_MESSAGE) {
460
+ console.log(`[Session] 收到 PREKEY_MESSAGE,尝试解密 (尝试 ${retryCount + 1}/${maxRetries + 1})`);
461
+ try {
462
+ // 【用户要求】先用尝试解密(真解密可能推动会话密钥变更,极度重要!)
463
+ plaintextBuffer =
464
+ await cipher.decryptPreKeyWhisperMessage(ciphertextBinary, "binary");
465
+ console.log(`[Session] PREKEY_MESSAGE 解密成功!`);
466
+ return decoder.decode(plaintextBuffer);
467
+ }
468
+ catch (decryptError) {
469
+ console.log(`[Session] 直接解密 PREKEY_MESSAGE 失败: ${decryptError instanceof Error ? decryptError.message : String(decryptError)}`);
470
+ // 如果解密失败,再处理 PREKEY 竞争的情况(但只在第一次尝试时处理)
471
+ if (existingSession && retryCount === 0) {
472
+ // 【用户要求】PREKEY 竞争时,双方始终优先以小地址发送的消息为最终依据
473
+ const myAddr = myAddress.toLowerCase();
474
+ const peerAddr = peerAddress.toLowerCase();
475
+ if (myAddr < peerAddr) {
476
+ // 我的地址较小,保留我的会话!不处理这个 PREKEY_MESSAGE,稍后重试
477
+ console.log(`[Session] 我的地址较小 (${myAddr} < ${peerAddr}),保留我的会话,稍后重试`);
478
+ throw new Error("PREKEY 竞争:我的地址较小,保留我的会话");
479
+ }
480
+ else {
481
+ // 我的地址较大,删除我的会话,用对方的 PREKEY_MESSAGE 建立新会话
482
+ console.log(`[Session] 我的地址较大 (${myAddr} > ${peerAddr}),删除我的会话,用对方的 PREKEY_MESSAGE 建立新会话`);
483
+ await this.store.removeSession(sessionKey);
484
+ existingSession = undefined;
485
+ // 现在删除了会话,重新尝试解密
486
+ console.log(`[Session] 已删除旧会话,重新尝试解密...`);
487
+ plaintextBuffer =
488
+ await cipher.decryptPreKeyWhisperMessage(ciphertextBinary, "binary");
489
+ console.log(`[Session] PREKEY_MESSAGE 解密成功,新会话已建立`);
490
+ return decoder.decode(plaintextBuffer);
491
+ }
492
+ }
493
+ else {
494
+ // 没有现有会话,或者不是第一次尝试,重新抛出解密错误
495
+ throw decryptError;
496
+ }
497
+ }
348
498
  }
349
499
  else {
350
- plaintextBuffer = await cipher.decryptPreKeyWhisperMessage(ciphertextBinary, "binary");
500
+ plaintextBuffer = await cipher.decryptWhisperMessage(ciphertextBinary, "binary");
351
501
  }
502
+ return decoder.decode(plaintextBuffer);
352
503
  }
353
- else {
354
- // 解密前检查会话状态
355
- /*const sessionBefore = await this.store.loadSession(sessionKey);
356
- console.log(
357
- `[Session Debug] 解密前会话状态: ${sessionBefore ? "存在" : "不存在"}`,
358
- );*/
359
- plaintextBuffer = await cipher.decryptWhisperMessage(ciphertextBinary, "binary");
360
- // 解密后检查会话状态
361
- /*const sessionAfter = await this.store.loadSession(sessionKey);
362
- console.log(
363
- `[Session Debug] 解密后会话状态: ${sessionAfter ? "存在" : "不存在"}`,
364
- );*/
365
- }
366
- }
367
- catch (error) {
368
- /*console.error(`[Session Debug] 解密失败:`);
369
- console.error(
370
- ` 错误类型: ${error instanceof Error ? error.constructor.name : typeof error}`,
371
- );
372
- console.error(
373
- ` 错误消息: ${error instanceof Error ? error.message : String(error)}`,
374
- );
375
- if (error instanceof Error && error.stack) {
376
- console.error(` 堆栈: ${error.stack.split("\n")[0]}`);
504
+ catch (error) {
505
+ console.error(`[Session Debug] 解密失败 (尝试 ${retryCount + 1}/${maxRetries + 1}):`);
506
+ console.error(` 错误类型: ${error instanceof Error ? error.constructor.name : typeof error}`);
507
+ console.error(` 错误消息: ${error instanceof Error ? error.message : String(error)}`);
508
+ if (error instanceof Error && error.stack) {
509
+ console.error(` 堆栈: ${error.stack.split("\n")[0]}`);
510
+ }
511
+ console.error(` 上下文:`);
512
+ console.error(` - myAddress: ${myAddress}`);
513
+ console.error(` - peerAddress: ${peerAddress}`);
514
+ console.error(` - msgType: ${msgType} (${msgType === MessageType.PREKEY_MESSAGE ? "PREKEY" : "WHISPER"})`);
515
+ console.error(` - sessionKey: ${sessionKey}`);
516
+ console.error(` - existingSession: ${existingSession ? "存在" : "不存在"}`);
517
+ console.error(` - ciphertext.length: ${ciphertext.byteLength}`);
518
+ const identityKey = await this.store.getIdentityKeyPair();
519
+ const regId = await this.store.getLocalRegistrationId();
520
+ console.error(` - identityKey: ${identityKey ? "存在" : "缺失"}`);
521
+ console.error(` - registrationId: ${regId}`);
522
+ if (retryCount >= maxRetries) {
523
+ throw error;
524
+ }
525
+ console.log(`[Session] 尝试重新建立会话...`);
526
+ try {
527
+ if (existingSession) {
528
+ console.log(`[Session] 删除旧会话`);
529
+ await this.store.removeSession(sessionKey);
530
+ existingSession = undefined;
531
+ }
532
+ if (msgType === MessageType.PREKEY_MESSAGE) {
533
+ console.log(`[Session] 收到的是 PREKEY_MESSAGE,等待发送方的 PreKey 即可重建会话`);
534
+ }
535
+ else {
536
+ console.log(`[Session] 收到的是 WHISPER_MESSAGE,需要让对方重新发送 PREKEY_MESSAGE`);
537
+ }
538
+ retryCount++;
539
+ await new Promise((resolve) => setTimeout(resolve, 100));
540
+ }
541
+ catch (rebuildError) {
542
+ console.error(`[Session] 重新建立会话失败:`, rebuildError);
543
+ throw error;
544
+ }
377
545
  }
378
- console.error(` 上下文:`);
379
- console.error(` - myAddress: ${myAddress}`);
380
- console.error(` - peerAddress: ${peerAddress}`);
381
- console.error(
382
- ` - msgType: ${msgType} (${msgType === MessageType.PREKEY_MESSAGE ? "PREKEY" : "WHISPER"})`,
383
- );
384
- console.error(` - sessionKey: ${sessionKey}`);
385
- console.error(
386
- ` - existingSession: ${existingSession ? "存在" : "不存在"}`,
387
- );
388
- console.error(` - ciphertext.length: ${ciphertext.byteLength}`);
389
- */
390
- console.log("error:", error);
391
- throw error;
392
546
  }
393
- return decoder.decode(plaintextBuffer);
547
+ throw new MessengerError(MessengerErrorCode.DECRYPTION_FAILED, "Decryption failed after multiple attempts");
394
548
  }
395
549
  /**
396
550
  * 获取本地身份公钥
@@ -407,4 +561,160 @@ export class MessengerSession {
407
561
  return identity.registrationId;
408
562
  }
409
563
  }
564
+ export class SessionStateManager {
565
+ store;
566
+ constructor(store) {
567
+ this.store = store;
568
+ }
569
+ /**
570
+ * 保存会话快照
571
+ */
572
+ async snapshotSession(sessionKey) {
573
+ const sessionData = await this.store.loadSession(sessionKey);
574
+ return {
575
+ sessionData: sessionData || null,
576
+ timestamp: Date.now(),
577
+ };
578
+ }
579
+ /**
580
+ * 回滚会话状态
581
+ */
582
+ async rollbackSession(sessionKey, snapshot) {
583
+ if (snapshot.sessionData) {
584
+ await this.store.storeSession(sessionKey, snapshot.sessionData);
585
+ console.log(`[SessionState] 回滚会话: ${sessionKey}`);
586
+ }
587
+ else {
588
+ await this.store.removeSession(sessionKey);
589
+ console.log(`[SessionState] 清除会话: ${sessionKey}`);
590
+ }
591
+ }
592
+ /**
593
+ * 提交会话状态(保留新会话)
594
+ */
595
+ async commitSession(_sessionKey) {
596
+ // 新会话已经在 decrypt 过程中保存到存储
597
+ // 这里可以添加额外的确认逻辑
598
+ console.log(`[SessionState] 提交新会话`);
599
+ }
600
+ }
601
+ export class DecryptionEngine {
602
+ sessionManager;
603
+ store;
604
+ constructor(store) {
605
+ this.store = store;
606
+ this.sessionManager = new SessionStateManager(store);
607
+ }
608
+ /**
609
+ * 统一解密入口
610
+ */
611
+ async decryptMessage(myAddress, peerAddress, ciphertext, msgType, peerDeviceId = DEFAULT_DEVICE_ID) {
612
+ const protocolAddress = new SignalProtocolAddress(peerAddress, peerDeviceId);
613
+ const sessionKey = protocolAddress.toString();
614
+ // 1. 保存会话快照(用于回滚)
615
+ const snapshot = await this.sessionManager.snapshotSession(sessionKey);
616
+ try {
617
+ if (msgType === MessageType.PREKEY_MESSAGE) {
618
+ return await this.handlePreKeyMessage(myAddress, peerAddress, ciphertext, protocolAddress, sessionKey, snapshot);
619
+ }
620
+ else {
621
+ return await this.handleWhisperMessage(myAddress, peerAddress, ciphertext, protocolAddress, sessionKey, snapshot);
622
+ }
623
+ }
624
+ catch (error) {
625
+ // 发生错误,回滚会话
626
+ await this.sessionManager.rollbackSession(sessionKey, snapshot);
627
+ return {
628
+ success: false,
629
+ sessionUpdated: false,
630
+ sessionRolledBack: true,
631
+ messageType: msgType === MessageType.PREKEY_MESSAGE
632
+ ? "PREKEY"
633
+ : "WHISPER",
634
+ error: error instanceof Error ? error.message : String(error),
635
+ };
636
+ }
637
+ }
638
+ /**
639
+ * 处理 PREKEY_MESSAGE
640
+ */
641
+ async handlePreKeyMessage(myAddress, peerAddress, ciphertext, protocolAddress, sessionKey, snapshot) {
642
+ console.log(`[Decrypt] 处理 PREKEY_MESSAGE from ${peerAddress}`);
643
+ const cipher = new SessionCipher(this.store, protocolAddress);
644
+ const decoder = new TextDecoder();
645
+ // 尝试解密(这会可能建立新会话)
646
+ const ciphertextBinary = this.arrayBufferToBinary(ciphertext);
647
+ const plaintextBuffer = await cipher.decryptPreKeyWhisperMessage(ciphertextBinary, "binary");
648
+ const plaintext = decoder.decode(plaintextBuffer);
649
+ console.log(`[Decrypt] PREKEY_MESSAGE 解密成功`);
650
+ // 地址优先级判断
651
+ const myAddr = myAddress.toLowerCase();
652
+ const peerAddr = peerAddress.toLowerCase();
653
+ if (myAddr < peerAddr) {
654
+ // 我是小地址,我的会话优先
655
+ // 回滚到之前的会话状态
656
+ await this.sessionManager.rollbackSession(sessionKey, snapshot);
657
+ console.log(`[Decrypt] 小地址(${myAddr})优先,回滚会话,但消息已解密`);
658
+ return {
659
+ success: true,
660
+ plaintext,
661
+ sessionUpdated: false,
662
+ sessionRolledBack: true,
663
+ messageType: "PREKEY",
664
+ };
665
+ }
666
+ else {
667
+ // 我是大地址,接受对方的会话
668
+ await this.sessionManager.commitSession(sessionKey);
669
+ console.log(`[Decrypt] 大地址(${myAddr})接受新会话`);
670
+ return {
671
+ success: true,
672
+ plaintext,
673
+ sessionUpdated: true,
674
+ sessionRolledBack: false,
675
+ messageType: "PREKEY",
676
+ };
677
+ }
678
+ }
679
+ /**
680
+ * 处理 WHISPER_MESSAGE
681
+ */
682
+ async handleWhisperMessage(_myAddress, peerAddress, ciphertext, protocolAddress, sessionKey, snapshot) {
683
+ console.log(`[Decrypt] 处理 WHISPER_MESSAGE from ${peerAddress}`);
684
+ // 检查是否有现有会话
685
+ const existingSession = await this.store.loadSession(sessionKey);
686
+ if (!existingSession) {
687
+ console.log(`[Decrypt] 无会话,WHISPER_MESSAGE 需要等待 PREKEY`);
688
+ await this.sessionManager.rollbackSession(sessionKey, snapshot);
689
+ return {
690
+ success: false,
691
+ sessionUpdated: false,
692
+ sessionRolledBack: false,
693
+ messageType: "WHISPER",
694
+ error: "NO_SESSION",
695
+ };
696
+ }
697
+ const cipher = new SessionCipher(this.store, protocolAddress);
698
+ const decoder = new TextDecoder();
699
+ // 尝试解密
700
+ const ciphertextBinary = this.arrayBufferToBinary(ciphertext);
701
+ const plaintextBuffer = await cipher.decryptWhisperMessage(ciphertextBinary, "binary");
702
+ console.log(`[Decrypt] WHISPER_MESSAGE 解密成功`);
703
+ return {
704
+ success: true,
705
+ plaintext: decoder.decode(plaintextBuffer),
706
+ sessionUpdated: true,
707
+ sessionRolledBack: false,
708
+ messageType: "WHISPER",
709
+ };
710
+ }
711
+ arrayBufferToBinary(buffer) {
712
+ const array = new Uint8Array(buffer);
713
+ let binary = "";
714
+ for (let i = 0; i < array.length; i++) {
715
+ binary += String.fromCharCode(array[i]);
716
+ }
717
+ return binary;
718
+ }
719
+ }
410
720
  //# sourceMappingURL=session.js.map