zapo-js 0.1.2 → 0.3.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 (630) hide show
  1. package/README.md +16 -4
  2. package/dist/appstate/WaAppStateCrypto.js +50 -42
  3. package/dist/appstate/WaAppStateSyncClient.js +215 -133
  4. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  5. package/dist/appstate/index.js +9 -7
  6. package/dist/appstate/utils.js +0 -5
  7. package/dist/auth/WaAuthClient.js +55 -57
  8. package/dist/auth/credentials-flow.js +195 -0
  9. package/dist/auth/index.js +1 -6
  10. package/dist/auth/pairing/WaPairingFlow.js +39 -32
  11. package/dist/auth/pairing/{WaPairingCodeCrypto.js → pairing-code-crypto.js} +35 -17
  12. package/dist/client/WaClient.js +338 -174
  13. package/dist/client/WaClientFactory.js +399 -66
  14. package/dist/client/connection/WaConnectionManager.js +23 -11
  15. package/dist/client/coordinators/WaAbPropsCoordinator.js +141 -0
  16. package/dist/client/coordinators/WaBusinessCoordinator.js +232 -0
  17. package/dist/client/coordinators/WaEmailCoordinator.js +63 -0
  18. package/dist/client/coordinators/WaGroupCoordinator.js +11 -7
  19. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +34 -8
  20. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +341 -118
  21. package/dist/client/coordinators/WaOfflineResumeCoordinator.js +114 -0
  22. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +97 -36
  23. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  24. package/dist/client/coordinators/WaProfileCoordinator.js +214 -0
  25. package/dist/client/coordinators/WaRetryCoordinator.js +184 -30
  26. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  27. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +184 -0
  28. package/dist/client/dirty.js +41 -21
  29. package/dist/client/events/abprops.js +43 -0
  30. package/dist/client/events/devices.js +72 -0
  31. package/dist/client/events/group.js +3 -11
  32. package/dist/client/events/identity.js +22 -0
  33. package/dist/client/events/privacy-token.js +38 -0
  34. package/dist/client/events/registration.js +42 -0
  35. package/dist/client/history-sync.js +50 -9
  36. package/dist/client/incoming.js +74 -7
  37. package/dist/client/mailbox.js +40 -23
  38. package/dist/client/media.js +243 -0
  39. package/dist/client/messages.js +245 -92
  40. package/dist/client/messaging/fanout.js +21 -11
  41. package/dist/client/messaging/participants.js +6 -4
  42. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  43. package/dist/client/tokens/cs-token.js +50 -0
  44. package/dist/client/tokens/tc-token.js +25 -0
  45. package/dist/crypto/core/index.js +5 -2
  46. package/dist/crypto/core/keys.js +4 -4
  47. package/dist/crypto/core/nonce.js +2 -0
  48. package/dist/crypto/core/primitives.js +0 -8
  49. package/dist/crypto/core/random.js +24 -8
  50. package/dist/crypto/core/xeddsa.js +57 -0
  51. package/dist/crypto/curves/X25519.js +43 -6
  52. package/dist/crypto/curves/constants.js +2 -1
  53. package/dist/crypto/index.js +3 -0
  54. package/dist/crypto/math/constants.js +13 -36
  55. package/dist/crypto/math/edwards.js +171 -44
  56. package/dist/crypto/math/fe.js +706 -0
  57. package/dist/crypto/math/mod.js +10 -3
  58. package/dist/esm/appstate/WaAppStateCrypto.js +40 -32
  59. package/dist/esm/appstate/WaAppStateSyncClient.js +206 -124
  60. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  61. package/dist/esm/appstate/index.js +2 -2
  62. package/dist/esm/appstate/{WaAppStateSyncResponseParser.js → response-parser.js} +1 -1
  63. package/dist/esm/appstate/utils.js +2 -5
  64. package/dist/esm/auth/WaAuthClient.js +52 -54
  65. package/dist/esm/auth/credentials-flow.js +190 -0
  66. package/dist/esm/auth/index.js +0 -2
  67. package/dist/esm/auth/pairing/WaPairingFlow.js +39 -32
  68. package/dist/esm/auth/pairing/{WaPairingCodeCrypto.js → pairing-code-crypto.js} +26 -10
  69. package/dist/esm/client/WaClient.js +339 -175
  70. package/dist/esm/client/WaClientFactory.js +401 -68
  71. package/dist/esm/client/connection/WaConnectionManager.js +23 -11
  72. package/dist/esm/client/coordinators/WaAbPropsCoordinator.js +137 -0
  73. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +229 -0
  74. package/dist/esm/client/coordinators/WaEmailCoordinator.js +60 -0
  75. package/dist/esm/client/coordinators/WaGroupCoordinator.js +11 -7
  76. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +36 -10
  77. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +337 -114
  78. package/dist/esm/client/coordinators/WaOfflineResumeCoordinator.js +110 -0
  79. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +97 -36
  80. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  81. package/dist/esm/client/coordinators/WaProfileCoordinator.js +211 -0
  82. package/dist/esm/client/coordinators/WaRetryCoordinator.js +186 -32
  83. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  84. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +180 -0
  85. package/dist/esm/client/dirty.js +41 -21
  86. package/dist/esm/client/events/abprops.js +40 -0
  87. package/dist/esm/client/events/devices.js +68 -0
  88. package/dist/esm/client/events/group.js +3 -11
  89. package/dist/esm/client/events/identity.js +19 -0
  90. package/dist/esm/client/events/privacy-token.js +35 -0
  91. package/dist/esm/client/events/registration.js +39 -0
  92. package/dist/esm/client/history-sync.js +50 -9
  93. package/dist/esm/client/incoming.js +74 -8
  94. package/dist/esm/client/mailbox.js +40 -23
  95. package/dist/esm/client/media.js +234 -0
  96. package/dist/esm/client/messages.js +244 -91
  97. package/dist/esm/client/messaging/fanout.js +22 -12
  98. package/dist/esm/client/messaging/participants.js +6 -4
  99. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  100. package/dist/esm/client/tokens/cs-token.js +46 -0
  101. package/dist/esm/client/tokens/tc-token.js +18 -0
  102. package/dist/esm/crypto/core/index.js +3 -2
  103. package/dist/esm/crypto/core/keys.js +1 -1
  104. package/dist/esm/crypto/core/nonce.js +2 -0
  105. package/dist/esm/crypto/core/primitives.js +0 -7
  106. package/dist/esm/crypto/core/random.js +23 -7
  107. package/dist/esm/crypto/core/xeddsa.js +53 -0
  108. package/dist/esm/crypto/curves/X25519.js +45 -8
  109. package/dist/esm/crypto/curves/constants.js +1 -0
  110. package/dist/esm/crypto/index.js +1 -0
  111. package/dist/esm/crypto/math/constants.js +12 -35
  112. package/dist/esm/crypto/math/edwards.js +174 -47
  113. package/dist/esm/crypto/math/fe.js +691 -0
  114. package/dist/esm/crypto/math/mod.js +10 -1
  115. package/dist/esm/index.js +1 -1
  116. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  117. package/dist/esm/infra/perf/BoundedTaskQueue.js +3 -1
  118. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  119. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  120. package/dist/esm/infra/perf/StoreLock.js +80 -0
  121. package/dist/esm/media/WaMediaCrypto.js +332 -55
  122. package/dist/esm/media/WaMediaTransferClient.js +69 -220
  123. package/dist/esm/media/constants.js +4 -1
  124. package/dist/esm/media/processor.js +1 -0
  125. package/dist/esm/message/WaMessageClient.js +26 -19
  126. package/dist/esm/message/addon-crypto.js +130 -3
  127. package/dist/esm/message/content.js +206 -14
  128. package/dist/esm/message/icdc.js +76 -0
  129. package/dist/esm/message/incoming.js +38 -24
  130. package/dist/esm/message/phash.js +35 -13
  131. package/dist/esm/message/reporting-token.js +17 -30
  132. package/dist/esm/message/use-case-secret.js +1 -1
  133. package/dist/esm/protocol/abprops.js +159 -0
  134. package/dist/esm/protocol/appstate.js +9 -40
  135. package/dist/esm/protocol/browser.js +24 -18
  136. package/dist/esm/protocol/constants.js +8 -4
  137. package/dist/esm/protocol/defaults.js +6 -0
  138. package/dist/esm/protocol/email.js +30 -0
  139. package/dist/esm/protocol/index.js +1 -2
  140. package/dist/esm/protocol/jid.js +142 -39
  141. package/dist/esm/protocol/message.js +61 -1
  142. package/dist/esm/protocol/nodes.js +8 -2
  143. package/dist/esm/protocol/notification.js +9 -1
  144. package/dist/esm/protocol/privacy-token.js +17 -0
  145. package/dist/esm/protocol/privacy.js +55 -0
  146. package/dist/esm/protocol/stream.js +26 -1
  147. package/dist/esm/retry/codec.js +216 -0
  148. package/dist/esm/retry/constants.js +1 -1
  149. package/dist/esm/retry/index.js +2 -2
  150. package/dist/esm/retry/parse.js +50 -30
  151. package/dist/esm/retry/reason.js +1 -1
  152. package/dist/esm/retry/replay.js +11 -7
  153. package/dist/esm/retry/tracker.js +50 -12
  154. package/dist/esm/signal/api/SignalDeviceSyncApi.js +52 -32
  155. package/dist/esm/signal/api/SignalDigestSyncApi.js +21 -15
  156. package/dist/esm/signal/api/SignalIdentitySyncApi.js +30 -15
  157. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +19 -8
  158. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  159. package/dist/esm/signal/api/SignalSessionSyncApi.js +17 -8
  160. package/dist/esm/signal/api/result-map.js +10 -0
  161. package/dist/esm/signal/constants.js +0 -4
  162. package/dist/esm/signal/crypto/WaAdvSignature.js +5 -45
  163. package/dist/esm/signal/crypto/constants.js +0 -4
  164. package/dist/esm/signal/{store/sqlite.js → encoding.js} +40 -29
  165. package/dist/esm/signal/group/SenderKeyChain.js +3 -3
  166. package/dist/esm/signal/group/SenderKeyCodec.js +8 -8
  167. package/dist/esm/signal/group/SenderKeyManager.js +131 -109
  168. package/dist/esm/signal/index.js +1 -0
  169. package/dist/esm/signal/registration/keygen.js +8 -5
  170. package/dist/esm/signal/registration/utils.js +3 -2
  171. package/dist/esm/signal/session/SignalProtocol.js +158 -81
  172. package/dist/esm/signal/session/SignalRatchet.js +21 -10
  173. package/dist/esm/signal/session/SignalSerializer.js +5 -6
  174. package/dist/esm/signal/session/SignalSession.js +11 -9
  175. package/dist/esm/signal/session/resolver.js +140 -105
  176. package/dist/esm/store/contracts/identity.store.js +1 -0
  177. package/dist/esm/store/contracts/message-secret.store.js +1 -0
  178. package/dist/esm/store/contracts/pre-key.store.js +1 -0
  179. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  180. package/dist/esm/store/contracts/session.store.js +1 -0
  181. package/dist/esm/store/createStore.js +143 -193
  182. package/dist/esm/store/index.js +5 -10
  183. package/dist/esm/store/locks/appstate.lock.js +26 -0
  184. package/dist/esm/store/locks/auth.lock.js +15 -0
  185. package/dist/esm/store/locks/contact.lock.js +20 -0
  186. package/dist/esm/store/locks/device-list.lock.js +20 -0
  187. package/dist/esm/store/locks/identity.lock.js +16 -0
  188. package/dist/esm/store/locks/message-secret.lock.js +17 -0
  189. package/dist/esm/store/locks/message.lock.js +21 -0
  190. package/dist/esm/store/locks/participants.lock.js +20 -0
  191. package/dist/esm/store/locks/pre-key.lock.js +27 -0
  192. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  193. package/dist/esm/store/locks/retry.lock.js +29 -0
  194. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  195. package/dist/esm/store/locks/session.lock.js +19 -0
  196. package/dist/esm/store/locks/signal.lock.js +39 -0
  197. package/dist/esm/store/locks/thread.lock.js +21 -0
  198. package/dist/esm/store/noop.store.js +21 -1
  199. package/dist/esm/store/providers/memory/appstate.store.js +22 -24
  200. package/dist/esm/store/providers/memory/device-list.store.js +13 -5
  201. package/dist/esm/store/providers/memory/identity.store.js +31 -0
  202. package/dist/esm/store/providers/memory/message-secret.store.js +81 -0
  203. package/dist/esm/store/providers/memory/participants.store.js +3 -0
  204. package/dist/esm/store/providers/memory/pre-key.store.js +97 -0
  205. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  206. package/dist/esm/store/providers/memory/retry.store.js +99 -10
  207. package/dist/esm/store/providers/memory/sender-key.store.js +6 -1
  208. package/dist/esm/store/providers/memory/session.store.js +45 -0
  209. package/dist/esm/store/providers/memory/signal.store.js +1 -147
  210. package/dist/esm/transport/WaComms.js +7 -4
  211. package/dist/esm/transport/WaWebSocket.js +9 -7
  212. package/dist/esm/transport/binary/constants.js +0 -30
  213. package/dist/esm/transport/binary/decoder.js +4 -4
  214. package/dist/esm/transport/binary/encoder.js +8 -15
  215. package/dist/esm/transport/binary/index.js +0 -1
  216. package/dist/esm/transport/index.js +6 -0
  217. package/dist/esm/transport/keepalive/WaKeepAlive.js +17 -8
  218. package/dist/esm/transport/node/WaMobileTcpSocket.js +114 -0
  219. package/dist/esm/transport/node/WaNodeOrchestrator.js +37 -22
  220. package/dist/esm/transport/node/builders/abprops.js +20 -0
  221. package/dist/esm/transport/node/builders/business.js +129 -0
  222. package/dist/esm/transport/node/builders/device.js +11 -0
  223. package/dist/esm/transport/node/builders/email.js +65 -0
  224. package/dist/esm/transport/node/builders/global.js +370 -0
  225. package/dist/esm/transport/node/builders/message.js +63 -239
  226. package/dist/esm/transport/node/builders/offline.js +14 -0
  227. package/dist/esm/transport/node/builders/pairing.js +0 -24
  228. package/dist/esm/transport/node/builders/prekeys.js +37 -40
  229. package/dist/esm/transport/node/builders/presence.js +13 -0
  230. package/dist/esm/transport/node/builders/privacy-token.js +37 -0
  231. package/dist/esm/transport/node/builders/privacy.js +48 -0
  232. package/dist/esm/transport/node/builders/profile.js +70 -0
  233. package/dist/esm/transport/node/builders/retry.js +11 -23
  234. package/dist/esm/transport/node/builders/usync.js +6 -2
  235. package/dist/esm/transport/node/helpers.js +43 -1
  236. package/dist/esm/transport/node/mex/argo-decoder.js +152 -0
  237. package/dist/esm/transport/node/mex/client.js +83 -0
  238. package/dist/esm/transport/node/mex/persist-ids.js +10 -0
  239. package/dist/esm/transport/node/usync.js +3 -33
  240. package/dist/esm/transport/node/xml.js +35 -14
  241. package/dist/esm/transport/noise/WaClientPayload.js +24 -19
  242. package/dist/esm/transport/noise/WaFrameCodec.js +2 -2
  243. package/dist/esm/transport/noise/WaMobileClientPayload.js +53 -0
  244. package/dist/esm/transport/noise/WaNoiseCert.js +9 -27
  245. package/dist/esm/transport/noise/WaNoiseSession.js +76 -34
  246. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  247. package/dist/esm/transport/stream/parse.js +8 -4
  248. package/dist/esm/util/bytes.js +22 -18
  249. package/dist/esm/util/index.js +5 -0
  250. package/dist/esm/util/primitives.js +3 -2
  251. package/dist/index.js +7 -1
  252. package/dist/infra/perf/BackgroundQueue.js +482 -0
  253. package/dist/infra/perf/BoundedTaskQueue.js +3 -1
  254. package/dist/infra/perf/PromiseDedup.js +24 -0
  255. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  256. package/dist/infra/perf/StoreLock.js +84 -0
  257. package/dist/media/WaMediaCrypto.js +328 -51
  258. package/dist/media/WaMediaTransferClient.js +72 -253
  259. package/dist/media/constants.js +5 -2
  260. package/dist/media/processor.js +2 -0
  261. package/dist/message/WaMessageClient.js +26 -19
  262. package/dist/message/addon-crypto.js +131 -0
  263. package/dist/message/content.js +211 -14
  264. package/dist/message/icdc.js +81 -0
  265. package/dist/message/incoming.js +38 -24
  266. package/dist/message/phash.js +35 -13
  267. package/dist/message/reporting-token.js +16 -30
  268. package/dist/message/use-case-secret.js +1 -1
  269. package/dist/protocol/abprops.js +163 -0
  270. package/dist/protocol/appstate.js +10 -41
  271. package/dist/protocol/browser.js +25 -18
  272. package/dist/protocol/constants.js +33 -2
  273. package/dist/protocol/defaults.js +6 -0
  274. package/dist/protocol/email.js +33 -0
  275. package/dist/protocol/index.js +8 -5
  276. package/dist/protocol/jid.js +149 -39
  277. package/dist/protocol/message.js +62 -2
  278. package/dist/protocol/nodes.js +8 -2
  279. package/dist/protocol/notification.js +10 -2
  280. package/dist/protocol/privacy-token.js +20 -0
  281. package/dist/protocol/privacy.js +58 -0
  282. package/dist/protocol/stream.js +27 -2
  283. package/dist/retry/codec.js +220 -0
  284. package/dist/retry/constants.js +1 -1
  285. package/dist/retry/index.js +5 -5
  286. package/dist/retry/parse.js +51 -30
  287. package/dist/retry/reason.js +1 -1
  288. package/dist/retry/replay.js +10 -6
  289. package/dist/retry/tracker.js +50 -12
  290. package/dist/signal/api/SignalDeviceSyncApi.js +51 -31
  291. package/dist/signal/api/SignalDigestSyncApi.js +21 -15
  292. package/dist/signal/api/SignalIdentitySyncApi.js +29 -14
  293. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +17 -6
  294. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  295. package/dist/signal/api/SignalSessionSyncApi.js +16 -7
  296. package/dist/signal/api/result-map.js +13 -0
  297. package/dist/signal/constants.js +1 -5
  298. package/dist/signal/crypto/WaAdvSignature.js +2 -44
  299. package/dist/signal/crypto/constants.js +1 -5
  300. package/dist/signal/{store/sqlite.js → encoding.js} +41 -25
  301. package/dist/signal/group/SenderKeyChain.js +2 -2
  302. package/dist/signal/group/SenderKeyCodec.js +8 -8
  303. package/dist/signal/group/SenderKeyManager.js +130 -108
  304. package/dist/signal/index.js +13 -1
  305. package/dist/signal/registration/keygen.js +7 -4
  306. package/dist/signal/registration/utils.js +3 -2
  307. package/dist/signal/session/SignalProtocol.js +158 -81
  308. package/dist/signal/session/SignalRatchet.js +19 -8
  309. package/dist/signal/session/SignalSerializer.js +5 -6
  310. package/dist/signal/session/SignalSession.js +11 -9
  311. package/dist/signal/session/resolver.js +138 -103
  312. package/dist/store/contracts/identity.store.js +2 -0
  313. package/dist/store/contracts/message-secret.store.js +2 -0
  314. package/dist/store/contracts/pre-key.store.js +2 -0
  315. package/dist/store/contracts/privacy-token.store.js +2 -0
  316. package/dist/store/contracts/session.store.js +2 -0
  317. package/dist/store/createStore.js +142 -192
  318. package/dist/store/index.js +23 -33
  319. package/dist/store/locks/appstate.lock.js +29 -0
  320. package/dist/store/locks/auth.lock.js +18 -0
  321. package/dist/store/locks/contact.lock.js +23 -0
  322. package/dist/store/locks/device-list.lock.js +23 -0
  323. package/dist/store/locks/identity.lock.js +19 -0
  324. package/dist/store/locks/message-secret.lock.js +20 -0
  325. package/dist/store/locks/message.lock.js +24 -0
  326. package/dist/store/locks/participants.lock.js +23 -0
  327. package/dist/store/locks/pre-key.lock.js +30 -0
  328. package/dist/store/locks/privacy-token.lock.js +21 -0
  329. package/dist/store/locks/retry.lock.js +32 -0
  330. package/dist/store/locks/sender-key.lock.js +55 -0
  331. package/dist/store/locks/session.lock.js +22 -0
  332. package/dist/store/locks/signal.lock.js +42 -0
  333. package/dist/store/locks/thread.lock.js +24 -0
  334. package/dist/store/noop.store.js +22 -2
  335. package/dist/store/providers/memory/appstate.store.js +22 -24
  336. package/dist/store/providers/memory/device-list.store.js +13 -5
  337. package/dist/store/providers/memory/identity.store.js +35 -0
  338. package/dist/store/providers/memory/message-secret.store.js +85 -0
  339. package/dist/store/providers/memory/participants.store.js +3 -0
  340. package/dist/store/providers/memory/pre-key.store.js +101 -0
  341. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  342. package/dist/store/providers/memory/retry.store.js +98 -9
  343. package/dist/store/providers/memory/sender-key.store.js +6 -1
  344. package/dist/store/providers/memory/session.store.js +49 -0
  345. package/dist/store/providers/memory/signal.store.js +1 -147
  346. package/dist/transport/WaComms.js +7 -4
  347. package/dist/transport/WaWebSocket.js +9 -7
  348. package/dist/transport/binary/constants.js +1 -31
  349. package/dist/transport/binary/decoder.js +4 -4
  350. package/dist/transport/binary/encoder.js +8 -15
  351. package/dist/transport/binary/index.js +0 -4
  352. package/dist/transport/index.js +17 -1
  353. package/dist/transport/keepalive/WaKeepAlive.js +17 -8
  354. package/dist/transport/node/WaMobileTcpSocket.js +118 -0
  355. package/dist/transport/node/WaNodeOrchestrator.js +36 -21
  356. package/dist/transport/node/builders/abprops.js +23 -0
  357. package/dist/transport/node/builders/business.js +137 -0
  358. package/dist/transport/node/builders/device.js +14 -0
  359. package/dist/transport/node/builders/email.js +72 -0
  360. package/dist/transport/node/builders/global.js +375 -0
  361. package/dist/transport/node/builders/message.js +64 -245
  362. package/dist/transport/node/builders/offline.js +17 -0
  363. package/dist/transport/node/builders/pairing.js +0 -26
  364. package/dist/transport/node/builders/prekeys.js +36 -39
  365. package/dist/transport/node/builders/presence.js +16 -0
  366. package/dist/transport/node/builders/privacy-token.js +42 -0
  367. package/dist/transport/node/builders/privacy.js +55 -0
  368. package/dist/transport/node/builders/profile.js +78 -0
  369. package/dist/transport/node/builders/retry.js +10 -22
  370. package/dist/transport/node/builders/usync.js +6 -2
  371. package/dist/transport/node/helpers.js +46 -1
  372. package/dist/transport/node/mex/argo-decoder.js +189 -0
  373. package/dist/transport/node/mex/client.js +86 -0
  374. package/dist/transport/node/mex/persist-ids.js +13 -0
  375. package/dist/transport/node/usync.js +2 -32
  376. package/dist/transport/node/xml.js +35 -14
  377. package/dist/transport/noise/WaClientPayload.js +26 -21
  378. package/dist/transport/noise/WaFrameCodec.js +1 -1
  379. package/dist/transport/noise/WaMobileClientPayload.js +56 -0
  380. package/dist/transport/noise/WaNoiseCert.js +8 -26
  381. package/dist/transport/noise/WaNoiseSession.js +75 -33
  382. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  383. package/dist/transport/stream/parse.js +7 -3
  384. package/dist/types/appstate/WaAppStateCrypto.d.ts +11 -8
  385. package/dist/types/appstate/WaAppStateSyncClient.d.ts +6 -2
  386. package/dist/types/appstate/encoding.d.ts +7 -0
  387. package/dist/types/appstate/index.d.ts +3 -3
  388. package/dist/types/appstate/{WaAppStateSyncResponseParser.d.ts → response-parser.d.ts} +1 -1
  389. package/dist/types/appstate/types.d.ts +1 -1
  390. package/dist/types/appstate/utils.d.ts +0 -2
  391. package/dist/types/auth/WaAuthClient.d.ts +9 -3
  392. package/dist/types/auth/credentials-flow.d.ts +20 -0
  393. package/dist/types/auth/index.d.ts +0 -2
  394. package/dist/types/auth/pairing/WaPairingFlow.d.ts +3 -2
  395. package/dist/types/auth/pairing/{WaPairingCodeCrypto.d.ts → pairing-code-crypto.d.ts} +6 -1
  396. package/dist/types/auth/types.d.ts +41 -0
  397. package/dist/types/client/WaClient.d.ts +44 -18
  398. package/dist/types/client/WaClientFactory.d.ts +22 -8
  399. package/dist/types/client/connection/WaConnectionManager.d.ts +2 -0
  400. package/dist/types/client/coordinators/WaAbPropsCoordinator.d.ts +26 -0
  401. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  402. package/dist/types/client/coordinators/WaEmailCoordinator.d.ts +24 -0
  403. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +9 -2
  404. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +29 -2
  405. package/dist/types/client/coordinators/WaOfflineResumeCoordinator.d.ts +31 -0
  406. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +16 -1
  407. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  408. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +38 -0
  409. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +12 -0
  410. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  411. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +55 -0
  412. package/dist/types/client/dirty.d.ts +3 -1
  413. package/dist/types/client/events/abprops.d.ts +14 -0
  414. package/dist/types/client/events/devices.d.ts +20 -0
  415. package/dist/types/client/events/identity.d.ts +9 -0
  416. package/dist/types/client/events/privacy-token.d.ts +7 -0
  417. package/dist/types/client/events/registration.d.ts +17 -0
  418. package/dist/types/client/history-sync.d.ts +9 -6
  419. package/dist/types/client/incoming.d.ts +9 -2
  420. package/dist/types/client/index.d.ts +1 -1
  421. package/dist/types/client/mailbox.d.ts +5 -5
  422. package/dist/types/client/media.d.ts +31 -0
  423. package/dist/types/client/messages.d.ts +3 -2
  424. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  425. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  426. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  427. package/dist/types/client/types.d.ts +151 -4
  428. package/dist/types/crypto/core/index.d.ts +3 -2
  429. package/dist/types/crypto/core/nonce.d.ts +2 -0
  430. package/dist/types/crypto/core/primitives.d.ts +1 -2
  431. package/dist/types/crypto/core/random.d.ts +2 -1
  432. package/dist/types/crypto/core/xeddsa.d.ts +2 -0
  433. package/dist/types/crypto/curves/constants.d.ts +1 -0
  434. package/dist/types/crypto/index.d.ts +2 -0
  435. package/dist/types/crypto/math/constants.d.ts +4 -2
  436. package/dist/types/crypto/math/fe.d.ts +30 -0
  437. package/dist/types/crypto/math/mod.d.ts +0 -2
  438. package/dist/types/crypto/math/types.d.ts +11 -4
  439. package/dist/types/index.d.ts +6 -3
  440. package/dist/types/infra/log/ConsoleLogger.d.ts +1 -1
  441. package/dist/types/infra/log/PinoLogger.d.ts +1 -1
  442. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  443. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  444. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  445. package/dist/types/infra/perf/StoreLock.d.ts +11 -0
  446. package/dist/types/media/WaMediaCrypto.d.ts +16 -6
  447. package/dist/types/media/WaMediaTransferClient.d.ts +6 -23
  448. package/dist/types/media/constants.d.ts +3 -1
  449. package/dist/types/media/index.d.ts +2 -1
  450. package/dist/types/media/processor.d.ts +28 -0
  451. package/dist/types/media/types.d.ts +19 -5
  452. package/dist/types/message/addon-crypto.d.ts +34 -3
  453. package/dist/types/message/content.d.ts +11 -1
  454. package/dist/types/message/icdc.d.ts +13 -0
  455. package/dist/types/message/reporting-token.d.ts +0 -1
  456. package/dist/types/message/types.d.ts +42 -11
  457. package/dist/types/protocol/abprops.d.ts +142 -0
  458. package/dist/types/protocol/appstate.d.ts +0 -11
  459. package/dist/types/protocol/browser.d.ts +1 -0
  460. package/dist/types/protocol/constants.d.ts +12 -4
  461. package/dist/types/protocol/defaults.d.ts +6 -0
  462. package/dist/types/protocol/email.d.ts +32 -0
  463. package/dist/types/protocol/index.d.ts +1 -2
  464. package/dist/types/protocol/jid.d.ts +20 -2
  465. package/dist/types/protocol/message.d.ts +60 -0
  466. package/dist/types/protocol/nodes.d.ts +6 -0
  467. package/dist/types/protocol/notification.d.ts +8 -0
  468. package/dist/types/protocol/privacy-token.d.ts +17 -0
  469. package/dist/types/protocol/privacy.d.ts +75 -0
  470. package/dist/types/protocol/stream.d.ts +31 -0
  471. package/dist/types/retry/codec.d.ts +3 -0
  472. package/dist/types/retry/index.d.ts +3 -3
  473. package/dist/types/retry/parse.d.ts +5 -2
  474. package/dist/types/retry/reason.d.ts +1 -1
  475. package/dist/types/retry/tracker.d.ts +1 -0
  476. package/dist/types/retry/types.d.ts +6 -1
  477. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +2 -1
  478. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +9 -0
  479. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +5 -3
  480. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  481. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  482. package/dist/types/signal/api/result-map.d.ts +1 -0
  483. package/dist/types/signal/constants.d.ts +0 -3
  484. package/dist/types/signal/crypto/WaAdvSignature.d.ts +0 -2
  485. package/dist/types/signal/crypto/constants.d.ts +0 -1
  486. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +9 -3
  487. package/dist/types/signal/group/SenderKeyChain.d.ts +1 -1
  488. package/dist/types/signal/group/SenderKeyManager.d.ts +17 -7
  489. package/dist/types/signal/index.d.ts +2 -0
  490. package/dist/types/signal/registration/utils.d.ts +2 -1
  491. package/dist/types/signal/session/SignalProtocol.d.ts +21 -6
  492. package/dist/types/signal/session/SignalSerializer.d.ts +2 -1
  493. package/dist/types/signal/session/resolver.d.ts +11 -4
  494. package/dist/types/signal/types.d.ts +16 -4
  495. package/dist/types/store/contracts/appstate.store.d.ts +1 -1
  496. package/dist/types/store/contracts/identity.store.d.ts +11 -0
  497. package/dist/types/store/contracts/message-secret.store.d.ts +16 -0
  498. package/dist/types/store/contracts/pre-key.store.d.ts +13 -0
  499. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  500. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  501. package/dist/types/store/contracts/session.store.d.ts +14 -0
  502. package/dist/types/store/contracts/signal.store.d.ts +1 -27
  503. package/dist/types/store/createStore.d.ts +1 -1
  504. package/dist/types/store/index.d.ts +12 -12
  505. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  506. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  507. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  508. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  509. package/dist/types/store/locks/identity.lock.d.ts +3 -0
  510. package/dist/types/store/locks/message-secret.lock.d.ts +3 -0
  511. package/dist/types/store/locks/message.lock.d.ts +3 -0
  512. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  513. package/dist/types/store/locks/pre-key.lock.d.ts +3 -0
  514. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  515. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  516. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  517. package/dist/types/store/locks/session.lock.d.ts +3 -0
  518. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  519. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  520. package/dist/types/store/noop.store.d.ts +4 -0
  521. package/dist/types/store/providers/memory/appstate.store.d.ts +1 -1
  522. package/dist/types/store/providers/memory/identity.store.d.ts +18 -0
  523. package/dist/types/store/providers/memory/message-secret.store.d.ts +21 -0
  524. package/dist/types/store/providers/memory/pre-key.store.d.ts +23 -0
  525. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  526. package/dist/types/store/providers/memory/retry.store.d.ts +15 -1
  527. package/dist/types/store/providers/memory/session.store.d.ts +21 -0
  528. package/dist/types/store/providers/memory/signal.store.d.ts +2 -43
  529. package/dist/types/store/providers/memory/thread.store.d.ts +1 -1
  530. package/dist/types/store/types.d.ts +69 -61
  531. package/dist/types/transport/WaWebSocket.d.ts +1 -1
  532. package/dist/types/transport/binary/constants.d.ts +0 -30
  533. package/dist/types/transport/binary/index.d.ts +0 -1
  534. package/dist/types/transport/index.d.ts +8 -1
  535. package/dist/types/transport/keepalive/WaKeepAlive.d.ts +4 -1
  536. package/dist/types/transport/node/WaMobileTcpSocket.d.ts +18 -0
  537. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +9 -6
  538. package/dist/types/transport/node/builders/abprops.d.ts +5 -0
  539. package/dist/types/transport/node/builders/business.d.ts +29 -0
  540. package/dist/types/transport/node/builders/device.d.ts +2 -0
  541. package/dist/types/transport/node/builders/email.d.ts +11 -0
  542. package/dist/types/transport/node/builders/global.d.ts +102 -0
  543. package/dist/types/transport/node/builders/message.d.ts +8 -7
  544. package/dist/types/transport/node/builders/offline.d.ts +2 -0
  545. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  546. package/dist/types/transport/node/builders/prekeys.d.ts +4 -3
  547. package/dist/types/transport/node/builders/presence.d.ts +6 -0
  548. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  549. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  550. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  551. package/dist/types/transport/node/builders/retry.d.ts +0 -1
  552. package/dist/types/transport/node/helpers.d.ts +8 -0
  553. package/dist/types/transport/node/mex/argo-decoder.d.ts +11 -0
  554. package/dist/types/transport/node/mex/client.d.ts +18 -0
  555. package/dist/types/transport/node/mex/persist-ids.d.ts +14 -0
  556. package/dist/types/transport/noise/WaMobileClientPayload.d.ts +29 -0
  557. package/dist/types/transport/noise/WaNoiseCert.d.ts +7 -1
  558. package/dist/types/transport/noise/WaNoiseSession.d.ts +4 -2
  559. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  560. package/dist/types/transport/types.d.ts +8 -0
  561. package/dist/types/util/bytes.d.ts +1 -1
  562. package/dist/types/util/index.d.ts +5 -0
  563. package/dist/types/util/primitives.d.ts +0 -1
  564. package/dist/util/bytes.js +22 -18
  565. package/dist/util/index.js +23 -0
  566. package/dist/util/primitives.js +2 -2
  567. package/package.json +34 -10
  568. package/proto/index.js +1 -1
  569. package/dist/auth/flow/WaAuthCredentialsFlow.js +0 -130
  570. package/dist/auth/pairing/constants.js +0 -5
  571. package/dist/client/connection/WaKeyShareCoordinator.js +0 -63
  572. package/dist/crypto/core/constants.js +0 -4
  573. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +0 -125
  574. package/dist/esm/auth/pairing/constants.js +0 -2
  575. package/dist/esm/client/connection/WaKeyShareCoordinator.js +0 -59
  576. package/dist/esm/crypto/core/constants.js +0 -1
  577. package/dist/esm/retry/outbound.js +0 -82
  578. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  579. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -250
  580. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  581. package/dist/esm/store/providers/sqlite/connection.js +0 -245
  582. package/dist/esm/store/providers/sqlite/contact.store.js +0 -74
  583. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -127
  584. package/dist/esm/store/providers/sqlite/message.store.js +0 -132
  585. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  586. package/dist/esm/store/providers/sqlite/participants.store.js +0 -77
  587. package/dist/esm/store/providers/sqlite/retry.store.js +0 -141
  588. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -198
  589. package/dist/esm/store/providers/sqlite/signal.store.js +0 -435
  590. package/dist/esm/store/providers/sqlite/table-names.js +0 -107
  591. package/dist/esm/store/providers/sqlite/thread.store.js +0 -85
  592. package/dist/esm/transport/node/builders/index.js +0 -8
  593. package/dist/retry/outbound.js +0 -87
  594. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  595. package/dist/store/providers/sqlite/appstate.store.js +0 -254
  596. package/dist/store/providers/sqlite/auth.store.js +0 -180
  597. package/dist/store/providers/sqlite/connection.js +0 -281
  598. package/dist/store/providers/sqlite/contact.store.js +0 -78
  599. package/dist/store/providers/sqlite/device-list.store.js +0 -131
  600. package/dist/store/providers/sqlite/message.store.js +0 -136
  601. package/dist/store/providers/sqlite/migrations.js +0 -350
  602. package/dist/store/providers/sqlite/participants.store.js +0 -81
  603. package/dist/store/providers/sqlite/retry.store.js +0 -145
  604. package/dist/store/providers/sqlite/sender-key.store.js +0 -202
  605. package/dist/store/providers/sqlite/signal.store.js +0 -439
  606. package/dist/store/providers/sqlite/table-names.js +0 -113
  607. package/dist/store/providers/sqlite/thread.store.js +0 -89
  608. package/dist/transport/node/builders/index.js +0 -42
  609. package/dist/types/appstate/store/sqlite.d.ts +0 -7
  610. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +0 -14
  611. package/dist/types/auth/pairing/constants.d.ts +0 -2
  612. package/dist/types/client/connection/WaKeyShareCoordinator.d.ts +0 -14
  613. package/dist/types/crypto/core/constants.d.ts +0 -1
  614. package/dist/types/retry/outbound.d.ts +0 -4
  615. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  616. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -17
  617. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  618. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  619. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -12
  620. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -15
  621. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -13
  622. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  623. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -12
  624. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -15
  625. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -24
  626. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -53
  627. package/dist/types/store/providers/sqlite/table-names.d.ts +0 -5
  628. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -13
  629. package/dist/types/transport/node/builders/index.d.ts +0 -8
  630. /package/dist/appstate/{WaAppStateSyncResponseParser.js → response-parser.js} +0 -0
@@ -0,0 +1,10 @@
1
+ function mergePreferredParsedResult(target, key, next, isPreferred) {
2
+ const current = target.get(key);
3
+ if (!current || !isPreferred(current)) {
4
+ target.set(key, next);
5
+ }
6
+ }
7
+ export function registerParsedResultByRawAndCanonicalKey(parsedByRawKey, parsedByCanonicalKey, rawKey, canonicalKey, result, isPreferred) {
8
+ mergePreferredParsedResult(parsedByRawKey, rawKey, result, isPreferred);
9
+ mergePreferredParsedResult(parsedByCanonicalKey, canonicalKey, result, isPreferred);
10
+ }
@@ -1,11 +1,7 @@
1
- import { SERIALIZED_PUB_KEY_PREFIX as CORE_SERIALIZED_PUB_KEY_PREFIX } from '../crypto/core/constants.js';
2
1
  import { TEXT_ENCODER } from '../util/bytes.js';
3
2
  export const SIGNAL_VERSION = 3;
4
3
  export const SIGNAL_GROUP_VERSION = 3;
5
- export const SERIALIZED_PUB_KEY_PREFIX = CORE_SERIALIZED_PUB_KEY_PREFIX;
6
- export const KEY_TYPE_CURVE25519 = 5;
7
4
  export const SIGNAL_MAC_SIZE = 8;
8
- export const SIGNATURE_SIZE = 64;
9
5
  export const MAX_PREV_SESSIONS = 40;
10
6
  export const MAX_UNUSED_KEYS = 2000;
11
7
  export const FUTURE_MESSAGES_MAX = 2000;
@@ -1,56 +1,16 @@
1
- import { ed25519VerifyRaw, importHmacKey, hmacSign, randomBytesAsync, sha512, toRawPubKey } from '../../crypto/index.js';
2
- import { clampCurvePrivateKeyInPlace, montgomeryToEdwardsPublic } from '../../crypto/curves/X25519.js';
3
- import { encodeExtendedPoint, scalarMultBase } from '../../crypto/math/edwards.js';
4
- import { bytesToBigIntLE, bigIntToBytesLE } from '../../crypto/math/le.js';
5
- import { modGroup } from '../../crypto/math/mod.js';
6
- import { ADV_PREFIX_ACCOUNT_SIGNATURE, ADV_PREFIX_DEVICE_SIGNATURE, ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE, ADV_PREFIX_HOSTED_DEVICE_SIGNATURE, SIGNAL_PREFIX_SIGNATURE_RANDOM } from '../crypto/constants.js';
7
- import { assertByteLength, concatBytes } from '../../util/bytes.js';
1
+ import { hmacSign, importHmacKey, toRawPubKey, xeddsaSign, xeddsaVerify } from '../../crypto/index.js';
2
+ import { ADV_PREFIX_ACCOUNT_SIGNATURE, ADV_PREFIX_DEVICE_SIGNATURE, ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE, ADV_PREFIX_HOSTED_DEVICE_SIGNATURE } from '../crypto/constants.js';
3
+ import { concatBytes } from '../../util/bytes.js';
8
4
  export { ADV_PREFIX_ACCOUNT_SIGNATURE, ADV_PREFIX_DEVICE_SIGNATURE, ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE, ADV_PREFIX_HOSTED_DEVICE_SIGNATURE } from '../crypto/constants.js';
9
- export async function verifySignalSignature(publicKey, message, signature) {
10
- if (!assertByteLength(signature, 64, 'invalid signal signature length', false)) {
11
- return false;
12
- }
13
- if ((signature[63] & 0x60) !== 0) {
14
- return false;
15
- }
16
- const signalSignature = new Uint8Array(signature);
17
- const signBit = signalSignature[63] & 0x80;
18
- signalSignature[63] &= 0x7f;
19
- const curvePublic = toRawPubKey(publicKey);
20
- const edPublic = montgomeryToEdwardsPublic(curvePublic, signBit);
21
- return ed25519VerifyRaw(edPublic, signalSignature, message);
22
- }
23
- export async function signSignalMessage(privateKey, message) {
24
- assertByteLength(privateKey, 32, `invalid curve25519 private key length ${privateKey.length}`);
25
- const clampedPrivateKey = clampCurvePrivateKeyInPlace(privateKey);
26
- const privateScalar = bytesToBigIntLE(clampedPrivateKey);
27
- const encodedPublic = encodeExtendedPoint(scalarMultBase(privateScalar));
28
- const pubKeySignBit = encodedPublic[31] & 0x80;
29
- const randomSuffix = await randomBytesAsync(64);
30
- const hashInput = concatBytes([
31
- SIGNAL_PREFIX_SIGNATURE_RANDOM,
32
- clampedPrivateKey,
33
- message,
34
- randomSuffix
35
- ]);
36
- const r = modGroup(bytesToBigIntLE(await sha512(hashInput)));
37
- const encodedR = encodeExtendedPoint(scalarMultBase(r));
38
- const hInput = concatBytes([encodedR, encodedPublic, message]);
39
- const h = modGroup(bytesToBigIntLE(await sha512(hInput)));
40
- const s = modGroup(r + h * privateScalar);
41
- const encodedS = bigIntToBytesLE(s, 32);
42
- encodedS[31] = (encodedS[31] & 0x7f) | pubKeySignBit;
43
- return concatBytes([encodedR, encodedS]);
44
- }
45
5
  export async function verifyDeviceIdentityAccountSignature(details, accountSignature, identityPublicKey, accountSignatureKey, isHosted = false) {
46
6
  const prefix = isHosted ? ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE : ADV_PREFIX_ACCOUNT_SIGNATURE;
47
7
  const message = concatBytes([prefix, details, identityPublicKey]);
48
- return verifySignalSignature(accountSignatureKey, message, accountSignature);
8
+ return xeddsaVerify(toRawPubKey(accountSignatureKey), message, accountSignature);
49
9
  }
50
10
  export async function generateDeviceSignature(details, identityKeyPair, accountSignatureKey, isHosted = false) {
51
11
  const prefix = isHosted ? ADV_PREFIX_HOSTED_DEVICE_SIGNATURE : ADV_PREFIX_DEVICE_SIGNATURE;
52
12
  const message = concatBytes([prefix, details, identityKeyPair.pubKey, accountSignatureKey]);
53
- return signSignalMessage(identityKeyPair.privKey, message);
13
+ return xeddsaSign(identityKeyPair.privKey, message);
54
14
  }
55
15
  export async function computeAdvIdentityHmac(secretKey, details) {
56
16
  const key = await importHmacKey(secretKey);
@@ -1,7 +1,3 @@
1
- export const SIGNAL_PREFIX_SIGNATURE_RANDOM = new Uint8Array([
2
- 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
3
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
4
- ]);
5
1
  export const ADV_PREFIX_ACCOUNT_SIGNATURE = new Uint8Array([6, 0]);
6
2
  export const ADV_PREFIX_DEVICE_SIGNATURE = new Uint8Array([6, 1]);
7
3
  export const ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE = new Uint8Array([6, 5]);
@@ -1,7 +1,7 @@
1
- import { proto } from '../../proto.js';
2
- import { WA_DEFAULTS } from '../../protocol/constants.js';
3
- import { assertByteLength } from '../../util/bytes.js';
4
- import { asBytes, asNumber, asOptionalBytes, asOptionalNumber, asString, toBoolOrUndef } from '../../util/coercion.js';
1
+ import { proto } from '../proto.js';
2
+ import { WA_DEFAULTS } from '../protocol/constants.js';
3
+ import { assertByteLength } from '../util/bytes.js';
4
+ import { asBytes, asNumber, asOptionalBytes, asOptionalNumber, asString, toBoolOrUndef } from '../util/coercion.js';
5
5
  export function toSignalAddressParts(address) {
6
6
  return {
7
7
  user: address.user,
@@ -46,7 +46,7 @@ export function decodeSignalSignedPreKeyRow(row) {
46
46
  uploaded: toBoolOrUndef(row.uploaded)
47
47
  };
48
48
  }
49
- function encodeSignalSessionSnapshot(session) {
49
+ export function encodeSignalSessionSnapshot(session) {
50
50
  return {
51
51
  sessionVersion: 3,
52
52
  localRegistrationId: session.local.regId,
@@ -56,7 +56,7 @@ function encodeSignalSessionSnapshot(session) {
56
56
  rootKey: session.rootKey,
57
57
  previousCounter: session.prevSendChainHighestIndex,
58
58
  senderChain: encodeSignalSendChain(session.sendChain),
59
- receiverChains: session.recvChains.map((chain) => encodeSignalRecvChain(chain)),
59
+ receiverChains: session.recvChains,
60
60
  pendingPreKey: session.initialExchangeInfo
61
61
  ? {
62
62
  preKeyId: session.initialExchangeInfo.remoteOneTimeId ?? undefined,
@@ -78,22 +78,17 @@ function encodeSignalSendChain(chain) {
78
78
  messageKeys: []
79
79
  };
80
80
  }
81
- function encodeSignalRecvChain(chain) {
81
+ export function encodeSignalRecvChain(chain) {
82
82
  return {
83
83
  senderRatchetKey: chain.ratchetPubKey,
84
84
  chainKey: {
85
85
  index: chain.nextMsgIndex,
86
86
  key: chain.chainKey
87
87
  },
88
- messageKeys: (chain.unusedMsgKeys ?? []).map((messageKey) => ({
89
- index: messageKey.index,
90
- cipherKey: messageKey.cipherKey,
91
- macKey: messageKey.macKey,
92
- iv: messageKey.iv
93
- }))
88
+ messageKeys: chain.unusedMsgKeys
94
89
  };
95
90
  }
96
- function decodeSignalMessageKey(messageKey, field) {
91
+ export function decodeSignalMessageKey(messageKey, field) {
97
92
  const cipherKey = asBytes(messageKey.cipherKey, `${field}.cipherKey`);
98
93
  assertByteLength(cipherKey, 32, `invalid ${field}.cipherKey length ${cipherKey.byteLength}`);
99
94
  const macKey = asBytes(messageKey.macKey, `${field}.macKey`);
@@ -107,7 +102,7 @@ function decodeSignalMessageKey(messageKey, field) {
107
102
  iv
108
103
  };
109
104
  }
110
- function decodeSignalRecvChain(chain, field) {
105
+ export function decodeSignalRecvChain(chain, field) {
111
106
  const chainKey = chain.chainKey;
112
107
  if (!chainKey) {
113
108
  throw new Error(`missing ${field}.chainKey`);
@@ -120,7 +115,7 @@ function decodeSignalRecvChain(chain, field) {
120
115
  ratchetPubKey,
121
116
  nextMsgIndex: asNumber(chainKey.index, `${field}.chainKey.index`),
122
117
  chainKey: chainKeyBytes,
123
- unusedMsgKeys: (chain.messageKeys ?? []).map((messageKey, index) => decodeSignalMessageKey(messageKey, `${field}.messageKeys[${index}]`))
118
+ unusedMsgKeys: chain.messageKeys ?? []
124
119
  };
125
120
  }
126
121
  function decodeSignalSendChain(chain, field) {
@@ -146,7 +141,7 @@ function decodeSignalSendChain(chain, field) {
146
141
  chainKey: chainKeyBytes
147
142
  };
148
143
  }
149
- function decodeSignalSessionSnapshot(session, field) {
144
+ export function decodeSignalSessionSnapshot(session, field) {
150
145
  const senderChain = session.senderChain;
151
146
  if (!senderChain) {
152
147
  throw new Error(`missing ${field}.senderChain`);
@@ -179,7 +174,7 @@ function decodeSignalSessionSnapshot(session, field) {
179
174
  },
180
175
  rootKey,
181
176
  sendChain: decodeSignalSendChain(senderChain, `${field}.senderChain`),
182
- recvChains: (session.receiverChains ?? []).map((chain, index) => decodeSignalRecvChain(chain, `${field}.receiverChains[${index}]`)),
177
+ recvChains: session.receiverChains ?? [],
183
178
  initialExchangeInfo: pendingPreKey
184
179
  ? {
185
180
  remoteOneTimeId: asOptionalNumber(pendingPreKey.preKeyId, `${field}.pendingPreKey.preKeyId`) ??
@@ -195,7 +190,7 @@ function decodeSignalSessionSnapshot(session, field) {
195
190
  export function encodeSignalSessionRecord(record) {
196
191
  return proto.RecordStructure.encode({
197
192
  currentSession: encodeSignalSessionSnapshot(record),
198
- previousSessions: record.prevSessions.map((session) => encodeSignalSessionSnapshot(session))
193
+ previousSessions: record.prevSessions
199
194
  }).finish();
200
195
  }
201
196
  export function decodeSignalSessionRecord(raw) {
@@ -206,7 +201,7 @@ export function decodeSignalSessionRecord(raw) {
206
201
  const current = decodeSignalSessionSnapshot(decoded.currentSession, 'signal_sessions.currentSession');
207
202
  return {
208
203
  ...current,
209
- prevSessions: (decoded.previousSessions ?? []).map((session, index) => decodeSignalSessionSnapshot(session, `signal_sessions.previousSessions[${index}]`))
204
+ prevSessions: decoded.previousSessions ?? []
210
205
  };
211
206
  }
212
207
  export function encodeSenderKeyRecord(record) {
@@ -222,10 +217,18 @@ export function encodeSenderKeyRecord(record) {
222
217
  public: record.signingPublicKey,
223
218
  private: record.signingPrivateKey
224
219
  },
225
- senderMessageKeys: (record.unusedMessageKeys ?? []).map((messageKey) => ({
226
- iteration: messageKey.iteration,
227
- seed: messageKey.seed
228
- }))
220
+ senderMessageKeys: (() => {
221
+ const src = record.unusedMessageKeys ?? [];
222
+ const arr = new Array(src.length);
223
+ for (let i = 0; i < src.length; i += 1) {
224
+ const messageKey = src[i];
225
+ arr[i] = {
226
+ iteration: messageKey.iteration,
227
+ seed: messageKey.seed
228
+ };
229
+ }
230
+ return arr;
231
+ })()
229
232
  }
230
233
  ]
231
234
  }).finish();
@@ -245,10 +248,18 @@ function decodeSenderKeyState(state, field) {
245
248
  signingPrivateKey: state.senderSigningKey.private !== null && state.senderSigningKey.private !== undefined
246
249
  ? asBytes(state.senderSigningKey.private, `${field}.senderSigningKey.private`)
247
250
  : undefined,
248
- unusedMessageKeys: (state.senderMessageKeys ?? []).map((messageKey, index) => ({
249
- iteration: asNumber(messageKey.iteration, `${field}.senderMessageKeys[${index}].iteration`),
250
- seed: asBytes(messageKey.seed, `${field}.senderMessageKeys[${index}].seed`)
251
- }))
251
+ unusedMessageKeys: (() => {
252
+ const src = state.senderMessageKeys ?? [];
253
+ const arr = new Array(src.length);
254
+ for (let i = 0; i < src.length; i += 1) {
255
+ const messageKey = src[i];
256
+ arr[i] = {
257
+ iteration: asNumber(messageKey.iteration, `${field}.senderMessageKeys[${i}].iteration`),
258
+ seed: asBytes(messageKey.seed, `${field}.senderMessageKeys[${i}].seed`)
259
+ };
260
+ }
261
+ return arr;
262
+ })()
252
263
  };
253
264
  }
254
265
  export function decodeSenderKeyRecord(raw, groupId, sender) {
@@ -281,7 +292,7 @@ export function decodeSenderKeyDistributionRow(row) {
281
292
  timestampMs: asNumber(row.timestamp_ms, 'sender_key_distribution.timestamp_ms')
282
293
  };
283
294
  }
284
- export function decodeSqliteCount(row, field) {
295
+ export function decodeStoreCount(row, field) {
285
296
  return row ? asNumber(row.count, field) : 0;
286
297
  }
287
298
  export function decodeSignalRemoteIdentity(raw) {
@@ -1,9 +1,9 @@
1
- import { hkdf, importHmacKey, hmacSign } from '../../crypto/index.js';
1
+ import { hkdf, hmacSign, importHmacKey } from '../../crypto/index.js';
2
2
  import { CHAIN_KEY_LABEL, MAX_UNUSED_KEYS, MESSAGE_KEY_LABEL, SENDER_KEY_FUTURE_MESSAGES_MAX, WHISPER_GROUP_INFO } from '../constants.js';
3
3
  import { assertByteLength, removeAt } from '../../util/bytes.js';
4
- export async function selectMessageKey(senderKey, targetIteration) {
4
+ export async function selectMessageKey(senderKey, targetIteration, futureMessagesMax) {
5
5
  const delta = targetIteration - senderKey.iteration;
6
- if (delta > SENDER_KEY_FUTURE_MESSAGES_MAX) {
6
+ if (delta > (futureMessagesMax ?? SENDER_KEY_FUTURE_MESSAGES_MAX)) {
7
7
  throw new Error('sender key message is too far in future');
8
8
  }
9
9
  const currentUnused = senderKey.unusedMessageKeys ?? [];
@@ -1,7 +1,8 @@
1
1
  import { readVersionedContent, toSerializedPubKey } from '../../crypto/index.js';
2
2
  import { proto } from '../../proto.js';
3
- import { SIGNATURE_SIZE, SIGNAL_GROUP_VERSION } from '../constants.js';
4
- import { assertByteLength, toBytesView } from '../../util/bytes.js';
3
+ import { SIGNAL_SIGNATURE_LENGTH } from '../api/constants.js';
4
+ import { SIGNAL_GROUP_VERSION } from '../constants.js';
5
+ import { assertByteLength } from '../../util/bytes.js';
5
6
  export function parseDistributionPayload(payload) {
6
7
  const body = readVersionedContent(payload, SIGNAL_GROUP_VERSION, 0);
7
8
  const decoded = proto.SenderKeyDistributionMessage.decode(body);
@@ -15,17 +16,16 @@ export function parseDistributionPayload(payload) {
15
16
  decoded.signingKey === undefined) {
16
17
  throw new Error('invalid sender key distribution message');
17
18
  }
18
- const chainKey = toBytesView(decoded.chainKey);
19
- assertByteLength(chainKey, 32, 'sender key distribution chainKey must be 32 bytes');
19
+ assertByteLength(decoded.chainKey, 32, 'sender key distribution chainKey must be 32 bytes');
20
20
  return {
21
21
  keyId: decoded.id,
22
22
  iteration: decoded.iteration,
23
- chainKey,
24
- signingPublicKey: toSerializedPubKey(toBytesView(decoded.signingKey))
23
+ chainKey: decoded.chainKey,
24
+ signingPublicKey: toSerializedPubKey(decoded.signingKey)
25
25
  };
26
26
  }
27
27
  export function parseSenderKeyMessage(versionContentMac) {
28
- const body = readVersionedContent(versionContentMac, SIGNAL_GROUP_VERSION, SIGNATURE_SIZE);
28
+ const body = readVersionedContent(versionContentMac, SIGNAL_GROUP_VERSION, SIGNAL_SIGNATURE_LENGTH);
29
29
  const decoded = proto.SenderKeyMessage.decode(body);
30
30
  if (decoded.id === null ||
31
31
  decoded.id === undefined ||
@@ -38,7 +38,7 @@ export function parseSenderKeyMessage(versionContentMac) {
38
38
  return {
39
39
  keyId: decoded.id,
40
40
  iteration: decoded.iteration,
41
- ciphertext: toBytesView(decoded.ciphertext),
41
+ ciphertext: decoded.ciphertext,
42
42
  versionContentMac
43
43
  };
44
44
  }
@@ -1,7 +1,9 @@
1
- import { aesCbcDecrypt, aesCbcEncrypt, importAesCbcKey, toSerializedPubKey, prependVersion, randomBytesAsync, randomIntAsync, X25519 } from '../../crypto/index.js';
1
+ import { aesCbcDecrypt, aesCbcEncrypt, importAesCbcKey, prependVersion, randomBytesAsync, randomIntAsync, toRawPubKey, toSerializedPubKey, X25519, xeddsaSign, xeddsaVerify } from '../../crypto/index.js';
2
+ import { StoreLock } from '../../infra/perf/StoreLock.js';
2
3
  import { proto } from '../../proto.js';
3
- import { SIGNAL_GROUP_VERSION, SIGNATURE_SIZE } from '../constants.js';
4
- import { signSignalMessage, verifySignalSignature } from '../crypto/WaAdvSignature.js';
4
+ import { signalAddressKey } from '../../protocol/jid.js';
5
+ import { SIGNAL_SIGNATURE_LENGTH } from '../api/constants.js';
6
+ import { SIGNAL_GROUP_VERSION } from '../constants.js';
5
7
  import { deriveSenderKeyMsgKey, selectMessageKey } from '../group/SenderKeyChain.js';
6
8
  import { parseDistributionPayload, parseSenderKeyMessage } from '../group/SenderKeyCodec.js';
7
9
  import { concatBytes } from '../../util/bytes.js';
@@ -23,144 +25,161 @@ async function aesCbcDecryptFromSeed(seed, ciphertext) {
23
25
  return aesCbcDecrypt(await importAesCbcKey(keyBytes), iv, ciphertext);
24
26
  }
25
27
  export class SenderKeyManager {
26
- constructor(store) {
28
+ constructor(store, options) {
29
+ this.senderLock = new StoreLock();
27
30
  this.store = store;
31
+ this.getFutureMessagesMax = options?.getFutureMessagesMax;
32
+ this.skipSignatureVerification = options?.skipSignatureVerification === true;
28
33
  }
29
- async createSenderKeyDistributionMessage(groupId, sender) {
30
- const senderKey = await this.ensureSenderKey(groupId, sender);
31
- const distributionProto = proto.SenderKeyDistributionMessage.encode({
32
- id: senderKey.keyId,
33
- iteration: senderKey.iteration,
34
- chainKey: senderKey.chainKey,
35
- signingKey: senderKey.signingPublicKey
36
- }).finish();
37
- const payload = prependVersion(distributionProto, SIGNAL_GROUP_VERSION);
38
- await this.store.upsertSenderKeyDistribution({
39
- groupId,
40
- sender,
41
- keyId: senderKey.keyId,
42
- timestampMs: Date.now()
34
+ async prepareGroupEncryption(groupId, sender, plaintext) {
35
+ return this.runWithSenderLock(groupId, sender, async () => {
36
+ const senderKey = await this.ensureSenderKeyInternal(groupId, sender);
37
+ if (!senderKey.signingPrivateKey) {
38
+ throw new Error('sender private signing key is missing');
39
+ }
40
+ const derived = await deriveSenderKeyMsgKey(senderKey.iteration, senderKey.chainKey);
41
+ await this.store.upsertSenderKey({
42
+ ...senderKey,
43
+ chainKey: derived.nextChainKey,
44
+ iteration: derived.messageKey.iteration + 1
45
+ });
46
+ const distributionProto = proto.SenderKeyDistributionMessage.encode({
47
+ id: senderKey.keyId,
48
+ iteration: senderKey.iteration,
49
+ chainKey: senderKey.chainKey,
50
+ signingKey: senderKey.signingPublicKey
51
+ }).finish();
52
+ const distributionMessage = {
53
+ groupId,
54
+ axolotlSenderKeyDistributionMessage: prependVersion(distributionProto, SIGNAL_GROUP_VERSION)
55
+ };
56
+ const messagePayload = await aesCbcEncryptFromSeed(derived.messageKey.seed, plaintext);
57
+ const senderKeyMessage = proto.SenderKeyMessage.encode({
58
+ id: senderKey.keyId,
59
+ iteration: derived.messageKey.iteration,
60
+ ciphertext: messagePayload
61
+ }).finish();
62
+ const versionedContent = prependVersion(senderKeyMessage, SIGNAL_GROUP_VERSION);
63
+ const signature = await xeddsaSign(senderKey.signingPrivateKey, versionedContent);
64
+ if (signature.length !== SIGNAL_SIGNATURE_LENGTH) {
65
+ throw new Error(`invalid sender key signature length ${signature.length}`);
66
+ }
67
+ const ciphertext = {
68
+ groupId,
69
+ sender,
70
+ keyId: senderKey.keyId,
71
+ iteration: derived.messageKey.iteration,
72
+ ciphertext: concatBytes([versionedContent, signature])
73
+ };
74
+ await this.store.upsertSenderKeyDistribution({
75
+ groupId,
76
+ sender,
77
+ keyId: senderKey.keyId,
78
+ timestampMs: Date.now()
79
+ });
80
+ return {
81
+ distributionMessage,
82
+ ciphertext,
83
+ keyId: senderKey.keyId
84
+ };
43
85
  });
44
- return {
45
- groupId,
46
- axolotlSenderKeyDistributionMessage: payload
47
- };
48
86
  }
49
- async filterParticipantsNeedingDistribution(groupId, sender, participants) {
87
+ async filterParticipantsNeedingDistribution(groupId, senderKeyId, participants) {
50
88
  if (participants.length === 0) {
51
89
  return [];
52
90
  }
53
- const senderKey = await this.ensureSenderKey(groupId, sender);
54
91
  const distributed = await this.store.getDeviceSenderKeyDistributions(groupId, participants);
55
- return participants.filter((_, index) => {
92
+ const pendingParticipants = new Array(participants.length);
93
+ let pendingCount = 0;
94
+ for (let index = 0; index < participants.length; index += 1) {
56
95
  const record = distributed[index];
57
- return !record || record.keyId !== senderKey.keyId;
58
- });
96
+ if (!record || record.keyId !== senderKeyId) {
97
+ pendingParticipants[pendingCount] = participants[index];
98
+ pendingCount += 1;
99
+ }
100
+ }
101
+ pendingParticipants.length = pendingCount;
102
+ return pendingParticipants;
59
103
  }
60
- async markSenderKeyDistributed(groupId, sender, participants) {
104
+ async markSenderKeyDistributed(groupId, senderKeyId, participants) {
61
105
  if (participants.length === 0) {
62
106
  return;
63
107
  }
64
- const senderKey = await this.ensureSenderKey(groupId, sender);
65
108
  const timestampMs = Date.now();
66
109
  const distributions = new Array(participants.length);
67
110
  for (let index = 0; index < participants.length; index += 1) {
68
111
  distributions[index] = {
69
112
  groupId,
70
113
  sender: participants[index],
71
- keyId: senderKey.keyId,
114
+ keyId: senderKeyId,
72
115
  timestampMs
73
116
  };
74
117
  }
75
118
  await this.store.upsertSenderKeyDistributions(distributions);
76
119
  }
77
120
  async processSenderKeyDistributionPayload(groupId, sender, payload) {
78
- if (groupId.length === 0) {
79
- throw new Error('sender key distribution missing groupId');
80
- }
81
- const parsed = parseDistributionPayload(payload);
82
- const record = {
83
- groupId,
84
- sender,
85
- keyId: parsed.keyId,
86
- iteration: parsed.iteration,
87
- chainKey: parsed.chainKey,
88
- signingPublicKey: parsed.signingPublicKey,
89
- unusedMessageKeys: []
90
- };
91
- await Promise.all([
92
- this.store.upsertSenderKey(record),
93
- this.store.upsertSenderKeyDistribution({
121
+ return this.runWithSenderLock(groupId, sender, async () => {
122
+ if (groupId.length === 0) {
123
+ throw new Error('sender key distribution missing groupId');
124
+ }
125
+ const parsed = parseDistributionPayload(payload);
126
+ const record = {
94
127
  groupId,
95
128
  sender,
96
129
  keyId: parsed.keyId,
97
- timestampMs: Date.now()
98
- })
99
- ]);
100
- return record;
101
- }
102
- async encryptGroupMessage(groupId, sender, plaintext) {
103
- const senderKey = await this.ensureSenderKey(groupId, sender);
104
- if (!senderKey.signingPrivateKey) {
105
- throw new Error('sender private signing key is missing');
106
- }
107
- const derived = await deriveSenderKeyMsgKey(senderKey.iteration, senderKey.chainKey);
108
- const messagePayload = await aesCbcEncryptFromSeed(derived.messageKey.seed, plaintext);
109
- const senderKeyMessage = proto.SenderKeyMessage.encode({
110
- id: senderKey.keyId,
111
- iteration: derived.messageKey.iteration,
112
- ciphertext: messagePayload
113
- }).finish();
114
- const versionedContent = prependVersion(senderKeyMessage, SIGNAL_GROUP_VERSION);
115
- const signature = await signSignalMessage(senderKey.signingPrivateKey, versionedContent);
116
- if (signature.length !== SIGNATURE_SIZE) {
117
- throw new Error(`invalid sender key signature length ${signature.length}`);
118
- }
119
- const ciphertext = concatBytes([versionedContent, signature]);
120
- await this.store.upsertSenderKey({
121
- ...senderKey,
122
- chainKey: derived.nextChainKey,
123
- iteration: derived.messageKey.iteration + 1
130
+ iteration: parsed.iteration,
131
+ chainKey: parsed.chainKey,
132
+ signingPublicKey: parsed.signingPublicKey,
133
+ unusedMessageKeys: []
134
+ };
135
+ await Promise.all([
136
+ this.store.upsertSenderKey(record),
137
+ this.store.upsertSenderKeyDistribution({
138
+ groupId,
139
+ sender,
140
+ keyId: parsed.keyId,
141
+ timestampMs: Date.now()
142
+ })
143
+ ]);
144
+ return record;
124
145
  });
125
- return {
126
- groupId,
127
- sender,
128
- keyId: senderKey.keyId,
129
- iteration: derived.messageKey.iteration,
130
- ciphertext
131
- };
132
146
  }
133
147
  async decryptGroupMessage(payload) {
134
- const parsed = parseSenderKeyMessage(payload.ciphertext);
135
- const senderKey = await this.store.getDeviceSenderKey(payload.groupId, payload.sender);
136
- if (!senderKey) {
137
- throw new Error('missing sender key');
138
- }
139
- if (senderKey.keyId !== parsed.keyId) {
140
- throw new Error('sender key id mismatch');
141
- }
142
- if (payload.keyId !== undefined &&
143
- payload.keyId !== null &&
144
- parsed.keyId !== payload.keyId) {
145
- throw new Error('sender key id mismatch');
146
- }
147
- if (payload.iteration !== undefined &&
148
- payload.iteration !== null &&
149
- parsed.iteration !== payload.iteration) {
150
- throw new Error('sender key iteration mismatch');
151
- }
152
- const signedContent = parsed.versionContentMac.subarray(0, parsed.versionContentMac.length - SIGNATURE_SIZE);
153
- const signature = parsed.versionContentMac.subarray(parsed.versionContentMac.length - SIGNATURE_SIZE);
154
- const validSignature = await verifySignalSignature(senderKey.signingPublicKey, signedContent, signature);
155
- if (!validSignature) {
156
- throw new Error('invalid sender key signature');
157
- }
158
- const selected = await selectMessageKey(senderKey, parsed.iteration);
159
- const plaintext = await aesCbcDecryptFromSeed(selected.messageKey.seed, parsed.ciphertext);
160
- await this.store.upsertSenderKey(selected.updatedRecord);
161
- return plaintext;
148
+ return this.runWithSenderLock(payload.groupId, payload.sender, async () => {
149
+ const parsed = parseSenderKeyMessage(payload.ciphertext);
150
+ const senderKey = await this.store.getDeviceSenderKey(payload.groupId, payload.sender);
151
+ if (!senderKey) {
152
+ throw new Error('missing sender key');
153
+ }
154
+ if (senderKey.keyId !== parsed.keyId) {
155
+ throw new Error('sender key id mismatch');
156
+ }
157
+ if (payload.keyId !== undefined &&
158
+ payload.keyId !== null &&
159
+ parsed.keyId !== payload.keyId) {
160
+ throw new Error('sender key id mismatch');
161
+ }
162
+ if (payload.iteration !== undefined &&
163
+ payload.iteration !== null &&
164
+ parsed.iteration !== payload.iteration) {
165
+ throw new Error('sender key iteration mismatch');
166
+ }
167
+ if (!this.skipSignatureVerification) {
168
+ const signedContent = parsed.versionContentMac.subarray(0, parsed.versionContentMac.length - SIGNAL_SIGNATURE_LENGTH);
169
+ const signature = parsed.versionContentMac.subarray(parsed.versionContentMac.length - SIGNAL_SIGNATURE_LENGTH);
170
+ const validSignature = await xeddsaVerify(toRawPubKey(senderKey.signingPublicKey), signedContent, signature);
171
+ if (!validSignature) {
172
+ throw new Error('invalid sender key signature');
173
+ }
174
+ }
175
+ const selected = await selectMessageKey(senderKey, parsed.iteration, this.getFutureMessagesMax?.());
176
+ // Keep decrypt + persist ordered: failed decrypt must not advance sender-key state.
177
+ const plaintext = await aesCbcDecryptFromSeed(selected.messageKey.seed, parsed.ciphertext);
178
+ await this.store.upsertSenderKey(selected.updatedRecord);
179
+ return plaintext;
180
+ });
162
181
  }
163
- async ensureSenderKey(groupId, sender) {
182
+ async ensureSenderKeyInternal(groupId, sender) {
164
183
  const existing = await this.store.getDeviceSenderKey(groupId, sender);
165
184
  if (existing) {
166
185
  return existing;
@@ -183,4 +202,7 @@ export class SenderKeyManager {
183
202
  await this.store.upsertSenderKey(created);
184
203
  return created;
185
204
  }
205
+ runWithSenderLock(groupId, sender, task) {
206
+ return this.senderLock.run(`senderKey:${groupId}:${signalAddressKey(sender)}`, task);
207
+ }
186
208
  }
@@ -1,3 +1,4 @@
1
+ export { decodeSignalPreKeyRow, decodeSignalRegistrationRow, decodeSignalRemoteIdentity, decodeSignalSessionRecord, decodeSignalSignedPreKeyRow, decodeSenderKeyDistributionRow, decodeSenderKeyRecord, decodeStoreCount, encodeSenderKeyRecord, encodeSignalSessionRecord, toSignalAddressParts } from './encoding.js';
1
2
  export { generatePreKeyPair, generateRegistrationId, generateRegistrationInfo, generateSignedPreKey } from './registration/keygen.js';
2
3
  export { buildPreKeyUploadIq, parsePreKeyUploadFailure } from './api/prekeys.js';
3
4
  export { SignalDigestSyncApi } from './api/SignalDigestSyncApi.js';
@@ -1,11 +1,14 @@
1
- import { randomIntAsync } from '../../crypto/index.js';
1
+ import { randomIntAsync, xeddsaSign } from '../../crypto/index.js';
2
2
  import { toSerializedPubKey } from '../../crypto/core/keys.js';
3
3
  import { X25519 } from '../../crypto/curves/X25519.js';
4
- import { signSignalMessage } from '../crypto/WaAdvSignature.js';
5
4
  export async function generateRegistrationInfo() {
5
+ const [registrationId, identityKeyPair] = await Promise.all([
6
+ generateRegistrationId(),
7
+ X25519.generateKeyPair()
8
+ ]);
6
9
  return {
7
- registrationId: await generateRegistrationId(),
8
- identityKeyPair: await X25519.generateKeyPair()
10
+ registrationId,
11
+ identityKeyPair
9
12
  };
10
13
  }
11
14
  export async function generatePreKeyPair(keyId) {
@@ -18,7 +21,7 @@ export async function generatePreKeyPair(keyId) {
18
21
  export async function generateSignedPreKey(keyId, signingPrivateKey) {
19
22
  const keyPair = await X25519.generateKeyPair();
20
23
  const serializedPubKey = toSerializedPubKey(keyPair.pubKey);
21
- const signature = await signSignalMessage(signingPrivateKey, serializedPubKey);
24
+ const signature = await xeddsaSign(signingPrivateKey, serializedPubKey);
22
25
  return {
23
26
  keyId,
24
27
  keyPair,