zapo-js 0.1.2 → 0.2.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 (468) hide show
  1. package/README.md +12 -4
  2. package/dist/appstate/WaAppStateCrypto.js +1 -1
  3. package/dist/appstate/WaAppStateSyncClient.js +138 -93
  4. package/dist/appstate/{store/sqlite.js → encoding.js} +13 -8
  5. package/dist/appstate/index.js +8 -6
  6. package/dist/appstate/utils.js +0 -5
  7. package/dist/auth/WaAuthClient.js +36 -47
  8. package/dist/auth/flow/WaAuthCredentialsFlow.js +7 -7
  9. package/dist/auth/index.js +1 -6
  10. package/dist/auth/pairing/WaPairingCodeCrypto.js +6 -4
  11. package/dist/auth/pairing/WaPairingFlow.js +13 -3
  12. package/dist/client/WaClient.js +225 -101
  13. package/dist/client/WaClientFactory.js +294 -44
  14. package/dist/client/connection/WaConnectionManager.js +19 -10
  15. package/dist/client/coordinators/WaBusinessCoordinator.js +241 -0
  16. package/dist/client/coordinators/WaGroupCoordinator.js +11 -7
  17. package/dist/client/coordinators/WaIncomingNodeCoordinator.js +1 -0
  18. package/dist/client/coordinators/WaMessageDispatchCoordinator.js +292 -99
  19. package/dist/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  20. package/dist/client/coordinators/WaPrivacyCoordinator.js +134 -0
  21. package/dist/client/coordinators/WaProfileCoordinator.js +212 -0
  22. package/dist/client/coordinators/WaRetryCoordinator.js +179 -27
  23. package/dist/client/coordinators/WaStreamControlCoordinator.js +18 -11
  24. package/dist/client/coordinators/WaTrustedContactTokenCoordinator.js +166 -0
  25. package/dist/client/dirty.js +40 -20
  26. package/dist/client/events/devices.js +72 -0
  27. package/dist/client/events/group.js +3 -11
  28. package/dist/client/events/identity.js +22 -0
  29. package/dist/client/events/privacy-token.js +39 -0
  30. package/dist/client/history-sync.js +50 -9
  31. package/dist/client/incoming.js +37 -7
  32. package/dist/client/mailbox.js +24 -23
  33. package/dist/client/messages.js +107 -31
  34. package/dist/client/messaging/fanout.js +21 -11
  35. package/dist/client/messaging/participants.js +6 -4
  36. package/dist/client/persistence/WriteBehindPersistence.js +129 -0
  37. package/dist/client/tokens/cs-token.js +50 -0
  38. package/dist/client/tokens/tc-token.js +25 -0
  39. package/dist/crypto/core/index.js +2 -2
  40. package/dist/crypto/core/keys.js +4 -4
  41. package/dist/crypto/core/nonce.js +2 -0
  42. package/dist/crypto/core/primitives.js +0 -8
  43. package/dist/crypto/core/random.js +22 -0
  44. package/dist/crypto/curves/X25519.js +25 -6
  45. package/dist/crypto/index.js +3 -0
  46. package/dist/crypto/math/constants.js +13 -36
  47. package/dist/crypto/math/edwards.js +171 -44
  48. package/dist/crypto/math/fe.js +706 -0
  49. package/dist/crypto/math/mod.js +10 -3
  50. package/dist/esm/appstate/WaAppStateCrypto.js +1 -1
  51. package/dist/esm/appstate/WaAppStateSyncClient.js +138 -93
  52. package/dist/esm/appstate/{store/sqlite.js → encoding.js} +13 -8
  53. package/dist/esm/appstate/index.js +2 -2
  54. package/dist/esm/appstate/utils.js +2 -5
  55. package/dist/esm/auth/WaAuthClient.js +36 -47
  56. package/dist/esm/auth/flow/WaAuthCredentialsFlow.js +7 -7
  57. package/dist/esm/auth/index.js +0 -2
  58. package/dist/esm/auth/pairing/WaPairingCodeCrypto.js +6 -4
  59. package/dist/esm/auth/pairing/WaPairingFlow.js +14 -4
  60. package/dist/esm/client/WaClient.js +225 -101
  61. package/dist/esm/client/WaClientFactory.js +295 -45
  62. package/dist/esm/client/connection/WaConnectionManager.js +19 -10
  63. package/dist/esm/client/coordinators/WaBusinessCoordinator.js +238 -0
  64. package/dist/esm/client/coordinators/WaGroupCoordinator.js +11 -7
  65. package/dist/esm/client/coordinators/WaIncomingNodeCoordinator.js +1 -0
  66. package/dist/esm/client/coordinators/WaMessageDispatchCoordinator.js +295 -102
  67. package/dist/esm/client/coordinators/WaPassiveTasksCoordinator.js +74 -31
  68. package/dist/esm/client/coordinators/WaPrivacyCoordinator.js +131 -0
  69. package/dist/esm/client/coordinators/WaProfileCoordinator.js +209 -0
  70. package/dist/esm/client/coordinators/WaRetryCoordinator.js +181 -29
  71. package/dist/esm/client/coordinators/WaStreamControlCoordinator.js +19 -12
  72. package/dist/esm/client/coordinators/WaTrustedContactTokenCoordinator.js +162 -0
  73. package/dist/esm/client/dirty.js +40 -20
  74. package/dist/esm/client/events/devices.js +68 -0
  75. package/dist/esm/client/events/group.js +3 -11
  76. package/dist/esm/client/events/identity.js +19 -0
  77. package/dist/esm/client/events/privacy-token.js +36 -0
  78. package/dist/esm/client/history-sync.js +50 -9
  79. package/dist/esm/client/incoming.js +38 -8
  80. package/dist/esm/client/mailbox.js +24 -23
  81. package/dist/esm/client/messages.js +108 -32
  82. package/dist/esm/client/messaging/fanout.js +22 -12
  83. package/dist/esm/client/messaging/participants.js +6 -4
  84. package/dist/esm/client/persistence/WriteBehindPersistence.js +125 -0
  85. package/dist/esm/client/tokens/cs-token.js +46 -0
  86. package/dist/esm/client/tokens/tc-token.js +18 -0
  87. package/dist/esm/crypto/core/index.js +2 -2
  88. package/dist/esm/crypto/core/keys.js +1 -1
  89. package/dist/esm/crypto/core/nonce.js +2 -0
  90. package/dist/esm/crypto/core/primitives.js +0 -7
  91. package/dist/esm/crypto/core/random.js +22 -1
  92. package/dist/esm/crypto/curves/X25519.js +25 -6
  93. package/dist/esm/crypto/index.js +1 -0
  94. package/dist/esm/crypto/math/constants.js +12 -35
  95. package/dist/esm/crypto/math/edwards.js +174 -47
  96. package/dist/esm/crypto/math/fe.js +691 -0
  97. package/dist/esm/crypto/math/mod.js +10 -1
  98. package/dist/esm/index.js +1 -1
  99. package/dist/esm/infra/perf/BackgroundQueue.js +478 -0
  100. package/dist/esm/infra/perf/BoundedTaskQueue.js +3 -1
  101. package/dist/esm/infra/perf/PromiseDedup.js +20 -0
  102. package/dist/esm/infra/perf/SharedExclusiveGate.js +109 -0
  103. package/dist/esm/infra/perf/StoreLock.js +77 -0
  104. package/dist/esm/media/WaMediaCrypto.js +95 -13
  105. package/dist/esm/media/WaMediaTransferClient.js +39 -47
  106. package/dist/esm/media/constants.js +2 -1
  107. package/dist/esm/message/WaMessageClient.js +26 -19
  108. package/dist/esm/message/content.js +195 -9
  109. package/dist/esm/message/icdc.js +76 -0
  110. package/dist/esm/message/incoming.js +24 -12
  111. package/dist/esm/message/phash.js +3 -1
  112. package/dist/esm/message/reporting-token.js +14 -27
  113. package/dist/esm/protocol/appstate.js +9 -40
  114. package/dist/esm/protocol/browser.js +10 -18
  115. package/dist/esm/protocol/constants.js +5 -3
  116. package/dist/esm/protocol/defaults.js +6 -0
  117. package/dist/esm/protocol/index.js +1 -2
  118. package/dist/esm/protocol/jid.js +105 -36
  119. package/dist/esm/protocol/message.js +61 -1
  120. package/dist/esm/protocol/nodes.js +2 -0
  121. package/dist/esm/protocol/notification.js +3 -1
  122. package/dist/esm/protocol/privacy-token.js +17 -0
  123. package/dist/esm/protocol/privacy.js +55 -0
  124. package/dist/esm/protocol/stream.js +26 -1
  125. package/dist/esm/retry/codec.js +216 -0
  126. package/dist/esm/retry/constants.js +1 -1
  127. package/dist/esm/retry/index.js +2 -2
  128. package/dist/esm/retry/parse.js +50 -30
  129. package/dist/esm/retry/replay.js +11 -7
  130. package/dist/esm/retry/tracker.js +50 -12
  131. package/dist/esm/signal/api/SignalDeviceSyncApi.js +49 -32
  132. package/dist/esm/signal/api/SignalDigestSyncApi.js +13 -9
  133. package/dist/esm/signal/api/SignalIdentitySyncApi.js +26 -11
  134. package/dist/esm/signal/api/SignalMissingPreKeysSyncApi.js +18 -7
  135. package/dist/esm/signal/api/SignalRotateKeyApi.js +4 -2
  136. package/dist/esm/signal/api/SignalSessionSyncApi.js +16 -7
  137. package/dist/esm/signal/api/result-map.js +10 -0
  138. package/dist/esm/signal/constants.js +0 -4
  139. package/dist/esm/signal/crypto/WaAdvSignature.js +12 -6
  140. package/dist/esm/signal/{store/sqlite.js → encoding.js} +78 -24
  141. package/dist/esm/signal/group/SenderKeyCodec.js +3 -2
  142. package/dist/esm/signal/group/SenderKeyManager.js +125 -106
  143. package/dist/esm/signal/index.js +1 -0
  144. package/dist/esm/signal/registration/keygen.js +6 -2
  145. package/dist/esm/signal/registration/utils.js +1 -0
  146. package/dist/esm/signal/session/SignalProtocol.js +150 -74
  147. package/dist/esm/signal/session/resolver.js +137 -102
  148. package/dist/esm/store/contracts/privacy-token.store.js +1 -0
  149. package/dist/esm/store/createStore.js +101 -187
  150. package/dist/esm/store/index.js +1 -10
  151. package/dist/esm/store/locks/appstate.lock.js +26 -0
  152. package/dist/esm/store/locks/auth.lock.js +15 -0
  153. package/dist/esm/store/locks/contact.lock.js +20 -0
  154. package/dist/esm/store/locks/device-list.lock.js +20 -0
  155. package/dist/esm/store/locks/message.lock.js +21 -0
  156. package/dist/esm/store/locks/participants.lock.js +20 -0
  157. package/dist/esm/store/locks/privacy-token.lock.js +18 -0
  158. package/dist/esm/store/locks/retry.lock.js +29 -0
  159. package/dist/esm/store/locks/sender-key.lock.js +52 -0
  160. package/dist/esm/store/locks/signal.lock.js +63 -0
  161. package/dist/esm/store/locks/thread.lock.js +21 -0
  162. package/dist/esm/store/noop.store.js +1 -1
  163. package/dist/esm/store/providers/memory/appstate.store.js +22 -24
  164. package/dist/esm/store/providers/memory/device-list.store.js +10 -5
  165. package/dist/esm/store/providers/memory/privacy-token.store.js +43 -0
  166. package/dist/esm/store/providers/memory/retry.store.js +77 -2
  167. package/dist/esm/store/providers/memory/sender-key.store.js +6 -1
  168. package/dist/esm/store/providers/memory/signal.store.js +36 -19
  169. package/dist/esm/transport/WaComms.js +3 -1
  170. package/dist/esm/transport/WaWebSocket.js +0 -6
  171. package/dist/esm/transport/binary/constants.js +0 -30
  172. package/dist/esm/transport/binary/decoder.js +4 -4
  173. package/dist/esm/transport/binary/encoder.js +8 -15
  174. package/dist/esm/transport/binary/index.js +0 -1
  175. package/dist/esm/transport/node/WaNodeOrchestrator.js +25 -19
  176. package/dist/esm/transport/node/builders/business.js +129 -0
  177. package/dist/esm/transport/node/builders/global.js +370 -0
  178. package/dist/esm/transport/node/builders/index.js +5 -2
  179. package/dist/esm/transport/node/builders/message.js +63 -239
  180. package/dist/esm/transport/node/builders/pairing.js +0 -24
  181. package/dist/esm/transport/node/builders/privacy-token.js +41 -0
  182. package/dist/esm/transport/node/builders/privacy.js +48 -0
  183. package/dist/esm/transport/node/builders/profile.js +70 -0
  184. package/dist/esm/transport/node/builders/retry.js +10 -22
  185. package/dist/esm/transport/node/builders/usync.js +6 -2
  186. package/dist/esm/transport/node/helpers.js +19 -1
  187. package/dist/esm/transport/node/usync.js +3 -33
  188. package/dist/esm/transport/node/xml.js +35 -14
  189. package/dist/esm/transport/noise/WaClientPayload.js +10 -10
  190. package/dist/esm/transport/noise/WaNoiseCert.js +3 -3
  191. package/dist/esm/transport/noise/WaNoiseSession.js +64 -23
  192. package/dist/esm/transport/noise/WaNoiseSocket.js +8 -4
  193. package/dist/esm/transport/stream/parse.js +8 -4
  194. package/dist/esm/util/bytes.js +22 -18
  195. package/dist/esm/util/index.js +5 -0
  196. package/dist/esm/util/primitives.js +3 -2
  197. package/dist/index.js +7 -1
  198. package/dist/infra/perf/BackgroundQueue.js +482 -0
  199. package/dist/infra/perf/BoundedTaskQueue.js +3 -1
  200. package/dist/infra/perf/PromiseDedup.js +24 -0
  201. package/dist/infra/perf/SharedExclusiveGate.js +113 -0
  202. package/dist/infra/perf/StoreLock.js +81 -0
  203. package/dist/media/WaMediaCrypto.js +94 -12
  204. package/dist/media/WaMediaTransferClient.js +39 -47
  205. package/dist/media/constants.js +2 -1
  206. package/dist/message/WaMessageClient.js +26 -19
  207. package/dist/message/content.js +198 -9
  208. package/dist/message/icdc.js +81 -0
  209. package/dist/message/incoming.js +24 -12
  210. package/dist/message/phash.js +3 -1
  211. package/dist/message/reporting-token.js +14 -28
  212. package/dist/protocol/appstate.js +10 -41
  213. package/dist/protocol/browser.js +10 -18
  214. package/dist/protocol/constants.js +21 -2
  215. package/dist/protocol/defaults.js +6 -0
  216. package/dist/protocol/index.js +8 -5
  217. package/dist/protocol/jid.js +111 -36
  218. package/dist/protocol/message.js +62 -2
  219. package/dist/protocol/nodes.js +2 -0
  220. package/dist/protocol/notification.js +3 -1
  221. package/dist/protocol/privacy-token.js +20 -0
  222. package/dist/protocol/privacy.js +58 -0
  223. package/dist/protocol/stream.js +27 -2
  224. package/dist/retry/codec.js +220 -0
  225. package/dist/retry/constants.js +1 -1
  226. package/dist/retry/index.js +5 -5
  227. package/dist/retry/parse.js +51 -30
  228. package/dist/retry/replay.js +10 -6
  229. package/dist/retry/tracker.js +50 -12
  230. package/dist/signal/api/SignalDeviceSyncApi.js +48 -31
  231. package/dist/signal/api/SignalDigestSyncApi.js +13 -9
  232. package/dist/signal/api/SignalIdentitySyncApi.js +25 -10
  233. package/dist/signal/api/SignalMissingPreKeysSyncApi.js +17 -6
  234. package/dist/signal/api/SignalRotateKeyApi.js +4 -2
  235. package/dist/signal/api/SignalSessionSyncApi.js +16 -7
  236. package/dist/signal/api/result-map.js +13 -0
  237. package/dist/signal/constants.js +1 -5
  238. package/dist/signal/crypto/WaAdvSignature.js +11 -5
  239. package/dist/signal/{store/sqlite.js → encoding.js} +79 -25
  240. package/dist/signal/group/SenderKeyCodec.js +4 -3
  241. package/dist/signal/group/SenderKeyManager.js +125 -106
  242. package/dist/signal/index.js +13 -1
  243. package/dist/signal/registration/keygen.js +6 -2
  244. package/dist/signal/registration/utils.js +1 -0
  245. package/dist/signal/session/SignalProtocol.js +150 -74
  246. package/dist/signal/session/resolver.js +135 -100
  247. package/dist/store/contracts/privacy-token.store.js +2 -0
  248. package/dist/store/createStore.js +101 -187
  249. package/dist/store/index.js +15 -33
  250. package/dist/store/locks/appstate.lock.js +29 -0
  251. package/dist/store/locks/auth.lock.js +18 -0
  252. package/dist/store/locks/contact.lock.js +23 -0
  253. package/dist/store/locks/device-list.lock.js +23 -0
  254. package/dist/store/locks/message.lock.js +24 -0
  255. package/dist/store/locks/participants.lock.js +23 -0
  256. package/dist/store/locks/privacy-token.lock.js +21 -0
  257. package/dist/store/locks/retry.lock.js +32 -0
  258. package/dist/store/locks/sender-key.lock.js +55 -0
  259. package/dist/store/locks/signal.lock.js +66 -0
  260. package/dist/store/locks/thread.lock.js +24 -0
  261. package/dist/store/noop.store.js +1 -1
  262. package/dist/store/providers/memory/appstate.store.js +22 -24
  263. package/dist/store/providers/memory/device-list.store.js +10 -5
  264. package/dist/store/providers/memory/privacy-token.store.js +47 -0
  265. package/dist/store/providers/memory/retry.store.js +77 -2
  266. package/dist/store/providers/memory/sender-key.store.js +6 -1
  267. package/dist/store/providers/memory/signal.store.js +36 -19
  268. package/dist/transport/WaComms.js +3 -1
  269. package/dist/transport/WaWebSocket.js +0 -6
  270. package/dist/transport/binary/constants.js +1 -31
  271. package/dist/transport/binary/decoder.js +4 -4
  272. package/dist/transport/binary/encoder.js +8 -15
  273. package/dist/transport/binary/index.js +0 -4
  274. package/dist/transport/node/WaNodeOrchestrator.js +24 -18
  275. package/dist/transport/node/builders/business.js +137 -0
  276. package/dist/transport/node/builders/global.js +375 -0
  277. package/dist/transport/node/builders/index.js +18 -9
  278. package/dist/transport/node/builders/message.js +64 -245
  279. package/dist/transport/node/builders/pairing.js +0 -26
  280. package/dist/transport/node/builders/privacy-token.js +46 -0
  281. package/dist/transport/node/builders/privacy.js +55 -0
  282. package/dist/transport/node/builders/profile.js +78 -0
  283. package/dist/transport/node/builders/retry.js +9 -21
  284. package/dist/transport/node/builders/usync.js +6 -2
  285. package/dist/transport/node/helpers.js +20 -1
  286. package/dist/transport/node/usync.js +2 -32
  287. package/dist/transport/node/xml.js +35 -14
  288. package/dist/transport/noise/WaClientPayload.js +13 -13
  289. package/dist/transport/noise/WaNoiseCert.js +2 -2
  290. package/dist/transport/noise/WaNoiseSession.js +64 -23
  291. package/dist/transport/noise/WaNoiseSocket.js +8 -4
  292. package/dist/transport/stream/parse.js +7 -3
  293. package/dist/types/appstate/encoding.d.ts +7 -0
  294. package/dist/types/appstate/index.d.ts +3 -3
  295. package/dist/types/appstate/utils.d.ts +0 -2
  296. package/dist/types/auth/flow/WaAuthCredentialsFlow.d.ts +1 -1
  297. package/dist/types/auth/index.d.ts +0 -2
  298. package/dist/types/auth/types.d.ts +1 -0
  299. package/dist/types/client/WaClient.d.ts +27 -12
  300. package/dist/types/client/WaClientFactory.d.ts +12 -4
  301. package/dist/types/client/connection/WaConnectionManager.d.ts +2 -0
  302. package/dist/types/client/coordinators/WaBusinessCoordinator.d.ts +57 -0
  303. package/dist/types/client/coordinators/WaIncomingNodeCoordinator.d.ts +3 -1
  304. package/dist/types/client/coordinators/WaMessageDispatchCoordinator.d.ts +14 -0
  305. package/dist/types/client/coordinators/WaPassiveTasksCoordinator.d.ts +4 -0
  306. package/dist/types/client/coordinators/WaPrivacyCoordinator.d.ts +26 -0
  307. package/dist/types/client/coordinators/WaProfileCoordinator.d.ts +36 -0
  308. package/dist/types/client/coordinators/WaRetryCoordinator.d.ts +6 -0
  309. package/dist/types/client/coordinators/WaStreamControlCoordinator.d.ts +3 -2
  310. package/dist/types/client/coordinators/WaTrustedContactTokenCoordinator.d.ts +45 -0
  311. package/dist/types/client/events/devices.d.ts +20 -0
  312. package/dist/types/client/events/identity.d.ts +9 -0
  313. package/dist/types/client/events/privacy-token.d.ts +7 -0
  314. package/dist/types/client/history-sync.d.ts +9 -6
  315. package/dist/types/client/incoming.d.ts +3 -1
  316. package/dist/types/client/index.d.ts +1 -1
  317. package/dist/types/client/mailbox.d.ts +3 -5
  318. package/dist/types/client/messages.d.ts +1 -2
  319. package/dist/types/client/persistence/WriteBehindPersistence.d.ts +34 -0
  320. package/dist/types/client/tokens/cs-token.d.ts +10 -0
  321. package/dist/types/client/tokens/tc-token.d.ts +5 -0
  322. package/dist/types/client/types.d.ts +51 -3
  323. package/dist/types/crypto/core/index.d.ts +2 -2
  324. package/dist/types/crypto/core/nonce.d.ts +2 -0
  325. package/dist/types/crypto/core/primitives.d.ts +0 -1
  326. package/dist/types/crypto/core/random.d.ts +1 -0
  327. package/dist/types/crypto/index.d.ts +1 -0
  328. package/dist/types/crypto/math/constants.d.ts +4 -2
  329. package/dist/types/crypto/math/fe.d.ts +30 -0
  330. package/dist/types/crypto/math/mod.d.ts +0 -2
  331. package/dist/types/crypto/math/types.d.ts +11 -4
  332. package/dist/types/index.d.ts +5 -3
  333. package/dist/types/infra/perf/BackgroundQueue.d.ts +58 -0
  334. package/dist/types/infra/perf/PromiseDedup.d.ts +4 -0
  335. package/dist/types/infra/perf/SharedExclusiveGate.d.ts +17 -0
  336. package/dist/types/infra/perf/StoreLock.d.ts +10 -0
  337. package/dist/types/media/WaMediaCrypto.d.ts +3 -2
  338. package/dist/types/media/WaMediaTransferClient.d.ts +3 -12
  339. package/dist/types/media/constants.d.ts +1 -1
  340. package/dist/types/media/index.d.ts +1 -1
  341. package/dist/types/media/types.d.ts +10 -2
  342. package/dist/types/message/content.d.ts +8 -0
  343. package/dist/types/message/icdc.d.ts +13 -0
  344. package/dist/types/message/reporting-token.d.ts +0 -1
  345. package/dist/types/message/types.d.ts +45 -6
  346. package/dist/types/protocol/appstate.d.ts +0 -11
  347. package/dist/types/protocol/constants.d.ts +7 -3
  348. package/dist/types/protocol/defaults.d.ts +6 -0
  349. package/dist/types/protocol/index.d.ts +1 -2
  350. package/dist/types/protocol/jid.d.ts +19 -2
  351. package/dist/types/protocol/message.d.ts +60 -0
  352. package/dist/types/protocol/nodes.d.ts +2 -0
  353. package/dist/types/protocol/notification.d.ts +2 -0
  354. package/dist/types/protocol/privacy-token.d.ts +17 -0
  355. package/dist/types/protocol/privacy.d.ts +75 -0
  356. package/dist/types/protocol/stream.d.ts +30 -0
  357. package/dist/types/retry/codec.d.ts +3 -0
  358. package/dist/types/retry/index.d.ts +3 -3
  359. package/dist/types/retry/parse.d.ts +5 -2
  360. package/dist/types/retry/tracker.d.ts +1 -0
  361. package/dist/types/retry/types.d.ts +6 -1
  362. package/dist/types/signal/api/SignalDeviceSyncApi.d.ts +2 -1
  363. package/dist/types/signal/api/SignalDigestSyncApi.d.ts +6 -0
  364. package/dist/types/signal/api/SignalIdentitySyncApi.d.ts +2 -0
  365. package/dist/types/signal/api/SignalRotateKeyApi.d.ts +4 -5
  366. package/dist/types/signal/api/SignalSessionSyncApi.d.ts +8 -6
  367. package/dist/types/signal/api/result-map.d.ts +1 -0
  368. package/dist/types/signal/constants.d.ts +0 -3
  369. package/dist/types/signal/{store/sqlite.d.ts → encoding.d.ts} +3 -3
  370. package/dist/types/signal/group/SenderKeyManager.d.ts +10 -5
  371. package/dist/types/signal/index.d.ts +2 -0
  372. package/dist/types/signal/session/SignalProtocol.d.ts +10 -4
  373. package/dist/types/signal/session/resolver.d.ts +7 -2
  374. package/dist/types/store/contracts/appstate.store.d.ts +1 -1
  375. package/dist/types/store/contracts/privacy-token.store.d.ts +16 -0
  376. package/dist/types/store/contracts/retry.store.d.ts +7 -0
  377. package/dist/types/store/contracts/signal.store.d.ts +7 -0
  378. package/dist/types/store/createStore.d.ts +1 -1
  379. package/dist/types/store/index.d.ts +5 -13
  380. package/dist/types/store/locks/appstate.lock.d.ts +3 -0
  381. package/dist/types/store/locks/auth.lock.d.ts +3 -0
  382. package/dist/types/store/locks/contact.lock.d.ts +3 -0
  383. package/dist/types/store/locks/device-list.lock.d.ts +2 -0
  384. package/dist/types/store/locks/message.lock.d.ts +3 -0
  385. package/dist/types/store/locks/participants.lock.d.ts +2 -0
  386. package/dist/types/store/locks/privacy-token.lock.d.ts +2 -0
  387. package/dist/types/store/locks/retry.lock.d.ts +2 -0
  388. package/dist/types/store/locks/sender-key.lock.d.ts +3 -0
  389. package/dist/types/store/locks/signal.lock.d.ts +3 -0
  390. package/dist/types/store/locks/thread.lock.d.ts +3 -0
  391. package/dist/types/store/providers/memory/appstate.store.d.ts +1 -1
  392. package/dist/types/store/providers/memory/privacy-token.store.d.ts +13 -0
  393. package/dist/types/store/providers/memory/retry.store.d.ts +8 -0
  394. package/dist/types/store/providers/memory/signal.store.d.ts +2 -1
  395. package/dist/types/store/types.d.ts +49 -61
  396. package/dist/types/transport/WaWebSocket.d.ts +0 -1
  397. package/dist/types/transport/binary/constants.d.ts +0 -30
  398. package/dist/types/transport/binary/index.d.ts +0 -1
  399. package/dist/types/transport/node/WaNodeOrchestrator.d.ts +3 -4
  400. package/dist/types/transport/node/builders/business.d.ts +29 -0
  401. package/dist/types/transport/node/builders/global.d.ts +102 -0
  402. package/dist/types/transport/node/builders/index.d.ts +5 -2
  403. package/dist/types/transport/node/builders/message.d.ts +8 -7
  404. package/dist/types/transport/node/builders/pairing.d.ts +0 -2
  405. package/dist/types/transport/node/builders/privacy-token.d.ts +9 -0
  406. package/dist/types/transport/node/builders/privacy.d.ts +7 -0
  407. package/dist/types/transport/node/builders/profile.d.ts +8 -0
  408. package/dist/types/transport/node/builders/retry.d.ts +0 -1
  409. package/dist/types/transport/node/helpers.d.ts +5 -0
  410. package/dist/types/transport/noise/WaNoiseSession.d.ts +3 -2
  411. package/dist/types/transport/noise/WaNoiseSocket.d.ts +4 -2
  412. package/dist/types/util/bytes.d.ts +1 -1
  413. package/dist/types/util/index.d.ts +5 -0
  414. package/dist/types/util/primitives.d.ts +0 -1
  415. package/dist/util/bytes.js +22 -18
  416. package/dist/util/index.js +23 -0
  417. package/dist/util/primitives.js +2 -2
  418. package/package.json +29 -7
  419. package/proto/index.js +1 -1
  420. package/dist/crypto/core/constants.js +0 -4
  421. package/dist/esm/crypto/core/constants.js +0 -1
  422. package/dist/esm/retry/outbound.js +0 -82
  423. package/dist/esm/store/providers/sqlite/BaseSqliteStore.js +0 -37
  424. package/dist/esm/store/providers/sqlite/appstate.store.js +0 -250
  425. package/dist/esm/store/providers/sqlite/auth.store.js +0 -176
  426. package/dist/esm/store/providers/sqlite/connection.js +0 -245
  427. package/dist/esm/store/providers/sqlite/contact.store.js +0 -74
  428. package/dist/esm/store/providers/sqlite/device-list.store.js +0 -127
  429. package/dist/esm/store/providers/sqlite/message.store.js +0 -132
  430. package/dist/esm/store/providers/sqlite/migrations.js +0 -347
  431. package/dist/esm/store/providers/sqlite/participants.store.js +0 -77
  432. package/dist/esm/store/providers/sqlite/retry.store.js +0 -141
  433. package/dist/esm/store/providers/sqlite/sender-key.store.js +0 -198
  434. package/dist/esm/store/providers/sqlite/signal.store.js +0 -435
  435. package/dist/esm/store/providers/sqlite/table-names.js +0 -107
  436. package/dist/esm/store/providers/sqlite/thread.store.js +0 -85
  437. package/dist/retry/outbound.js +0 -87
  438. package/dist/store/providers/sqlite/BaseSqliteStore.js +0 -41
  439. package/dist/store/providers/sqlite/appstate.store.js +0 -254
  440. package/dist/store/providers/sqlite/auth.store.js +0 -180
  441. package/dist/store/providers/sqlite/connection.js +0 -281
  442. package/dist/store/providers/sqlite/contact.store.js +0 -78
  443. package/dist/store/providers/sqlite/device-list.store.js +0 -131
  444. package/dist/store/providers/sqlite/message.store.js +0 -136
  445. package/dist/store/providers/sqlite/migrations.js +0 -350
  446. package/dist/store/providers/sqlite/participants.store.js +0 -81
  447. package/dist/store/providers/sqlite/retry.store.js +0 -145
  448. package/dist/store/providers/sqlite/sender-key.store.js +0 -202
  449. package/dist/store/providers/sqlite/signal.store.js +0 -439
  450. package/dist/store/providers/sqlite/table-names.js +0 -113
  451. package/dist/store/providers/sqlite/thread.store.js +0 -89
  452. package/dist/types/appstate/store/sqlite.d.ts +0 -7
  453. package/dist/types/crypto/core/constants.d.ts +0 -1
  454. package/dist/types/retry/outbound.d.ts +0 -4
  455. package/dist/types/store/providers/sqlite/BaseSqliteStore.d.ts +0 -12
  456. package/dist/types/store/providers/sqlite/appstate.store.d.ts +0 -17
  457. package/dist/types/store/providers/sqlite/auth.store.d.ts +0 -10
  458. package/dist/types/store/providers/sqlite/connection.d.ts +0 -10
  459. package/dist/types/store/providers/sqlite/contact.store.d.ts +0 -12
  460. package/dist/types/store/providers/sqlite/device-list.store.d.ts +0 -15
  461. package/dist/types/store/providers/sqlite/message.store.d.ts +0 -13
  462. package/dist/types/store/providers/sqlite/migrations.d.ts +0 -3
  463. package/dist/types/store/providers/sqlite/participants.store.d.ts +0 -12
  464. package/dist/types/store/providers/sqlite/retry.store.d.ts +0 -15
  465. package/dist/types/store/providers/sqlite/sender-key.store.d.ts +0 -24
  466. package/dist/types/store/providers/sqlite/signal.store.d.ts +0 -53
  467. package/dist/types/store/providers/sqlite/table-names.d.ts +0 -5
  468. package/dist/types/store/providers/sqlite/thread.store.d.ts +0 -13
@@ -10,12 +10,12 @@ exports.decodeSignalSessionRecord = decodeSignalSessionRecord;
10
10
  exports.encodeSenderKeyRecord = encodeSenderKeyRecord;
11
11
  exports.decodeSenderKeyRecord = decodeSenderKeyRecord;
12
12
  exports.decodeSenderKeyDistributionRow = decodeSenderKeyDistributionRow;
13
- exports.decodeSqliteCount = decodeSqliteCount;
13
+ exports.decodeStoreCount = decodeStoreCount;
14
14
  exports.decodeSignalRemoteIdentity = decodeSignalRemoteIdentity;
15
- const _proto_1 = require("../../proto.js");
16
- const constants_1 = require("../../protocol/constants");
17
- const bytes_1 = require("../../util/bytes");
18
- const coercion_1 = require("../../util/coercion");
15
+ const _proto_1 = require("../proto.js");
16
+ const constants_1 = require("../protocol/constants");
17
+ const bytes_1 = require("../util/bytes");
18
+ const coercion_1 = require("../util/coercion");
19
19
  function toSignalAddressParts(address) {
20
20
  return {
21
21
  user: address.user,
@@ -70,7 +70,13 @@ function encodeSignalSessionSnapshot(session) {
70
70
  rootKey: session.rootKey,
71
71
  previousCounter: session.prevSendChainHighestIndex,
72
72
  senderChain: encodeSignalSendChain(session.sendChain),
73
- receiverChains: session.recvChains.map((chain) => encodeSignalRecvChain(chain)),
73
+ receiverChains: (() => {
74
+ const src = session.recvChains;
75
+ const arr = new Array(src.length);
76
+ for (let i = 0; i < src.length; i += 1)
77
+ arr[i] = encodeSignalRecvChain(src[i]);
78
+ return arr;
79
+ })(),
74
80
  pendingPreKey: session.initialExchangeInfo
75
81
  ? {
76
82
  preKeyId: session.initialExchangeInfo.remoteOneTimeId ?? undefined,
@@ -99,12 +105,20 @@ function encodeSignalRecvChain(chain) {
99
105
  index: chain.nextMsgIndex,
100
106
  key: chain.chainKey
101
107
  },
102
- messageKeys: (chain.unusedMsgKeys ?? []).map((messageKey) => ({
103
- index: messageKey.index,
104
- cipherKey: messageKey.cipherKey,
105
- macKey: messageKey.macKey,
106
- iv: messageKey.iv
107
- }))
108
+ messageKeys: (() => {
109
+ const src = chain.unusedMsgKeys ?? [];
110
+ const arr = new Array(src.length);
111
+ for (let i = 0; i < src.length; i += 1) {
112
+ const messageKey = src[i];
113
+ arr[i] = {
114
+ index: messageKey.index,
115
+ cipherKey: messageKey.cipherKey,
116
+ macKey: messageKey.macKey,
117
+ iv: messageKey.iv
118
+ };
119
+ }
120
+ return arr;
121
+ })()
108
122
  };
109
123
  }
110
124
  function decodeSignalMessageKey(messageKey, field) {
@@ -134,7 +148,13 @@ function decodeSignalRecvChain(chain, field) {
134
148
  ratchetPubKey,
135
149
  nextMsgIndex: (0, coercion_1.asNumber)(chainKey.index, `${field}.chainKey.index`),
136
150
  chainKey: chainKeyBytes,
137
- unusedMsgKeys: (chain.messageKeys ?? []).map((messageKey, index) => decodeSignalMessageKey(messageKey, `${field}.messageKeys[${index}]`))
151
+ unusedMsgKeys: (() => {
152
+ const src = chain.messageKeys ?? [];
153
+ const arr = new Array(src.length);
154
+ for (let i = 0; i < src.length; i += 1)
155
+ arr[i] = decodeSignalMessageKey(src[i], `${field}.messageKeys[${i}]`);
156
+ return arr;
157
+ })()
138
158
  };
139
159
  }
140
160
  function decodeSignalSendChain(chain, field) {
@@ -193,7 +213,13 @@ function decodeSignalSessionSnapshot(session, field) {
193
213
  },
194
214
  rootKey,
195
215
  sendChain: decodeSignalSendChain(senderChain, `${field}.senderChain`),
196
- recvChains: (session.receiverChains ?? []).map((chain, index) => decodeSignalRecvChain(chain, `${field}.receiverChains[${index}]`)),
216
+ recvChains: (() => {
217
+ const src = session.receiverChains ?? [];
218
+ const arr = new Array(src.length);
219
+ for (let i = 0; i < src.length; i += 1)
220
+ arr[i] = decodeSignalRecvChain(src[i], `${field}.receiverChains[${i}]`);
221
+ return arr;
222
+ })(),
197
223
  initialExchangeInfo: pendingPreKey
198
224
  ? {
199
225
  remoteOneTimeId: (0, coercion_1.asOptionalNumber)(pendingPreKey.preKeyId, `${field}.pendingPreKey.preKeyId`) ??
@@ -209,7 +235,13 @@ function decodeSignalSessionSnapshot(session, field) {
209
235
  function encodeSignalSessionRecord(record) {
210
236
  return _proto_1.proto.RecordStructure.encode({
211
237
  currentSession: encodeSignalSessionSnapshot(record),
212
- previousSessions: record.prevSessions.map((session) => encodeSignalSessionSnapshot(session))
238
+ previousSessions: (() => {
239
+ const src = record.prevSessions;
240
+ const arr = new Array(src.length);
241
+ for (let i = 0; i < src.length; i += 1)
242
+ arr[i] = encodeSignalSessionSnapshot(src[i]);
243
+ return arr;
244
+ })()
213
245
  }).finish();
214
246
  }
215
247
  function decodeSignalSessionRecord(raw) {
@@ -220,7 +252,13 @@ function decodeSignalSessionRecord(raw) {
220
252
  const current = decodeSignalSessionSnapshot(decoded.currentSession, 'signal_sessions.currentSession');
221
253
  return {
222
254
  ...current,
223
- prevSessions: (decoded.previousSessions ?? []).map((session, index) => decodeSignalSessionSnapshot(session, `signal_sessions.previousSessions[${index}]`))
255
+ prevSessions: (() => {
256
+ const src = decoded.previousSessions ?? [];
257
+ const arr = new Array(src.length);
258
+ for (let i = 0; i < src.length; i += 1)
259
+ arr[i] = decodeSignalSessionSnapshot(src[i], `signal_sessions.previousSessions[${i}]`);
260
+ return arr;
261
+ })()
224
262
  };
225
263
  }
226
264
  function encodeSenderKeyRecord(record) {
@@ -236,10 +274,18 @@ function encodeSenderKeyRecord(record) {
236
274
  public: record.signingPublicKey,
237
275
  private: record.signingPrivateKey
238
276
  },
239
- senderMessageKeys: (record.unusedMessageKeys ?? []).map((messageKey) => ({
240
- iteration: messageKey.iteration,
241
- seed: messageKey.seed
242
- }))
277
+ senderMessageKeys: (() => {
278
+ const src = record.unusedMessageKeys ?? [];
279
+ const arr = new Array(src.length);
280
+ for (let i = 0; i < src.length; i += 1) {
281
+ const messageKey = src[i];
282
+ arr[i] = {
283
+ iteration: messageKey.iteration,
284
+ seed: messageKey.seed
285
+ };
286
+ }
287
+ return arr;
288
+ })()
243
289
  }
244
290
  ]
245
291
  }).finish();
@@ -259,10 +305,18 @@ function decodeSenderKeyState(state, field) {
259
305
  signingPrivateKey: state.senderSigningKey.private !== null && state.senderSigningKey.private !== undefined
260
306
  ? (0, coercion_1.asBytes)(state.senderSigningKey.private, `${field}.senderSigningKey.private`)
261
307
  : undefined,
262
- unusedMessageKeys: (state.senderMessageKeys ?? []).map((messageKey, index) => ({
263
- iteration: (0, coercion_1.asNumber)(messageKey.iteration, `${field}.senderMessageKeys[${index}].iteration`),
264
- seed: (0, coercion_1.asBytes)(messageKey.seed, `${field}.senderMessageKeys[${index}].seed`)
265
- }))
308
+ unusedMessageKeys: (() => {
309
+ const src = state.senderMessageKeys ?? [];
310
+ const arr = new Array(src.length);
311
+ for (let i = 0; i < src.length; i += 1) {
312
+ const messageKey = src[i];
313
+ arr[i] = {
314
+ iteration: (0, coercion_1.asNumber)(messageKey.iteration, `${field}.senderMessageKeys[${i}].iteration`),
315
+ seed: (0, coercion_1.asBytes)(messageKey.seed, `${field}.senderMessageKeys[${i}].seed`)
316
+ };
317
+ }
318
+ return arr;
319
+ })()
266
320
  };
267
321
  }
268
322
  function decodeSenderKeyRecord(raw, groupId, sender) {
@@ -295,7 +349,7 @@ function decodeSenderKeyDistributionRow(row) {
295
349
  timestampMs: (0, coercion_1.asNumber)(row.timestamp_ms, 'sender_key_distribution.timestamp_ms')
296
350
  };
297
351
  }
298
- function decodeSqliteCount(row, field) {
352
+ function decodeStoreCount(row, field) {
299
353
  return row ? (0, coercion_1.asNumber)(row.count, field) : 0;
300
354
  }
301
355
  function decodeSignalRemoteIdentity(raw) {
@@ -4,10 +4,11 @@ exports.parseDistributionPayload = parseDistributionPayload;
4
4
  exports.parseSenderKeyMessage = parseSenderKeyMessage;
5
5
  const _crypto_1 = require("../../crypto/index.js");
6
6
  const _proto_1 = require("../../proto.js");
7
- const constants_1 = require("../constants");
7
+ const constants_1 = require("../api/constants");
8
+ const constants_2 = require("../constants");
8
9
  const bytes_1 = require("../../util/bytes");
9
10
  function parseDistributionPayload(payload) {
10
- const body = (0, _crypto_1.readVersionedContent)(payload, constants_1.SIGNAL_GROUP_VERSION, 0);
11
+ const body = (0, _crypto_1.readVersionedContent)(payload, constants_2.SIGNAL_GROUP_VERSION, 0);
11
12
  const decoded = _proto_1.proto.SenderKeyDistributionMessage.decode(body);
12
13
  if (decoded.id === null ||
13
14
  decoded.id === undefined ||
@@ -29,7 +30,7 @@ function parseDistributionPayload(payload) {
29
30
  };
30
31
  }
31
32
  function parseSenderKeyMessage(versionContentMac) {
32
- const body = (0, _crypto_1.readVersionedContent)(versionContentMac, constants_1.SIGNAL_GROUP_VERSION, constants_1.SIGNATURE_SIZE);
33
+ const body = (0, _crypto_1.readVersionedContent)(versionContentMac, constants_2.SIGNAL_GROUP_VERSION, constants_1.SIGNAL_SIGNATURE_LENGTH);
33
34
  const decoded = _proto_1.proto.SenderKeyMessage.decode(body);
34
35
  if (decoded.id === null ||
35
36
  decoded.id === undefined ||
@@ -2,8 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SenderKeyManager = void 0;
4
4
  const _crypto_1 = require("../../crypto/index.js");
5
+ const StoreLock_1 = require("../../infra/perf/StoreLock");
5
6
  const _proto_1 = require("../../proto.js");
6
- const constants_1 = require("../constants");
7
+ const jid_1 = require("../../protocol/jid");
8
+ const constants_1 = require("../api/constants");
9
+ const constants_2 = require("../constants");
7
10
  const WaAdvSignature_1 = require("../crypto/WaAdvSignature");
8
11
  const SenderKeyChain_1 = require("../group/SenderKeyChain");
9
12
  const SenderKeyCodec_1 = require("../group/SenderKeyCodec");
@@ -27,143 +30,156 @@ async function aesCbcDecryptFromSeed(seed, ciphertext) {
27
30
  }
28
31
  class SenderKeyManager {
29
32
  constructor(store) {
33
+ this.senderLock = new StoreLock_1.StoreLock();
30
34
  this.store = store;
31
35
  }
32
- async createSenderKeyDistributionMessage(groupId, sender) {
33
- const senderKey = await this.ensureSenderKey(groupId, sender);
34
- const distributionProto = _proto_1.proto.SenderKeyDistributionMessage.encode({
35
- id: senderKey.keyId,
36
- iteration: senderKey.iteration,
37
- chainKey: senderKey.chainKey,
38
- signingKey: senderKey.signingPublicKey
39
- }).finish();
40
- const payload = (0, _crypto_1.prependVersion)(distributionProto, constants_1.SIGNAL_GROUP_VERSION);
41
- await this.store.upsertSenderKeyDistribution({
42
- groupId,
43
- sender,
44
- keyId: senderKey.keyId,
45
- timestampMs: Date.now()
36
+ async prepareGroupEncryption(groupId, sender, plaintext) {
37
+ return this.runWithSenderLock(groupId, sender, async () => {
38
+ const senderKey = await this.ensureSenderKeyInternal(groupId, sender);
39
+ if (!senderKey.signingPrivateKey) {
40
+ throw new Error('sender private signing key is missing');
41
+ }
42
+ const derived = await (0, SenderKeyChain_1.deriveSenderKeyMsgKey)(senderKey.iteration, senderKey.chainKey);
43
+ await this.store.upsertSenderKey({
44
+ ...senderKey,
45
+ chainKey: derived.nextChainKey,
46
+ iteration: derived.messageKey.iteration + 1
47
+ });
48
+ const distributionProto = _proto_1.proto.SenderKeyDistributionMessage.encode({
49
+ id: senderKey.keyId,
50
+ iteration: senderKey.iteration,
51
+ chainKey: senderKey.chainKey,
52
+ signingKey: senderKey.signingPublicKey
53
+ }).finish();
54
+ const distributionMessage = {
55
+ groupId,
56
+ axolotlSenderKeyDistributionMessage: (0, _crypto_1.prependVersion)(distributionProto, constants_2.SIGNAL_GROUP_VERSION)
57
+ };
58
+ const messagePayload = await aesCbcEncryptFromSeed(derived.messageKey.seed, plaintext);
59
+ const senderKeyMessage = _proto_1.proto.SenderKeyMessage.encode({
60
+ id: senderKey.keyId,
61
+ iteration: derived.messageKey.iteration,
62
+ ciphertext: messagePayload
63
+ }).finish();
64
+ const versionedContent = (0, _crypto_1.prependVersion)(senderKeyMessage, constants_2.SIGNAL_GROUP_VERSION);
65
+ const signature = await (0, WaAdvSignature_1.signSignalMessage)(senderKey.signingPrivateKey, versionedContent);
66
+ if (signature.length !== constants_1.SIGNAL_SIGNATURE_LENGTH) {
67
+ throw new Error(`invalid sender key signature length ${signature.length}`);
68
+ }
69
+ const ciphertext = {
70
+ groupId,
71
+ sender,
72
+ keyId: senderKey.keyId,
73
+ iteration: derived.messageKey.iteration,
74
+ ciphertext: (0, bytes_1.concatBytes)([versionedContent, signature])
75
+ };
76
+ await this.store.upsertSenderKeyDistribution({
77
+ groupId,
78
+ sender,
79
+ keyId: senderKey.keyId,
80
+ timestampMs: Date.now()
81
+ });
82
+ return {
83
+ distributionMessage,
84
+ ciphertext,
85
+ keyId: senderKey.keyId
86
+ };
46
87
  });
47
- return {
48
- groupId,
49
- axolotlSenderKeyDistributionMessage: payload
50
- };
51
88
  }
52
- async filterParticipantsNeedingDistribution(groupId, sender, participants) {
89
+ async filterParticipantsNeedingDistribution(groupId, senderKeyId, participants) {
53
90
  if (participants.length === 0) {
54
91
  return [];
55
92
  }
56
- const senderKey = await this.ensureSenderKey(groupId, sender);
57
93
  const distributed = await this.store.getDeviceSenderKeyDistributions(groupId, participants);
58
- return participants.filter((_, index) => {
94
+ const pendingParticipants = new Array(participants.length);
95
+ let pendingCount = 0;
96
+ for (let index = 0; index < participants.length; index += 1) {
59
97
  const record = distributed[index];
60
- return !record || record.keyId !== senderKey.keyId;
61
- });
98
+ if (!record || record.keyId !== senderKeyId) {
99
+ pendingParticipants[pendingCount] = participants[index];
100
+ pendingCount += 1;
101
+ }
102
+ }
103
+ pendingParticipants.length = pendingCount;
104
+ return pendingParticipants;
62
105
  }
63
- async markSenderKeyDistributed(groupId, sender, participants) {
106
+ async markSenderKeyDistributed(groupId, senderKeyId, participants) {
64
107
  if (participants.length === 0) {
65
108
  return;
66
109
  }
67
- const senderKey = await this.ensureSenderKey(groupId, sender);
68
110
  const timestampMs = Date.now();
69
111
  const distributions = new Array(participants.length);
70
112
  for (let index = 0; index < participants.length; index += 1) {
71
113
  distributions[index] = {
72
114
  groupId,
73
115
  sender: participants[index],
74
- keyId: senderKey.keyId,
116
+ keyId: senderKeyId,
75
117
  timestampMs
76
118
  };
77
119
  }
78
120
  await this.store.upsertSenderKeyDistributions(distributions);
79
121
  }
80
122
  async processSenderKeyDistributionPayload(groupId, sender, payload) {
81
- if (groupId.length === 0) {
82
- throw new Error('sender key distribution missing groupId');
83
- }
84
- const parsed = (0, SenderKeyCodec_1.parseDistributionPayload)(payload);
85
- const record = {
86
- groupId,
87
- sender,
88
- keyId: parsed.keyId,
89
- iteration: parsed.iteration,
90
- chainKey: parsed.chainKey,
91
- signingPublicKey: parsed.signingPublicKey,
92
- unusedMessageKeys: []
93
- };
94
- await Promise.all([
95
- this.store.upsertSenderKey(record),
96
- this.store.upsertSenderKeyDistribution({
123
+ return this.runWithSenderLock(groupId, sender, async () => {
124
+ if (groupId.length === 0) {
125
+ throw new Error('sender key distribution missing groupId');
126
+ }
127
+ const parsed = (0, SenderKeyCodec_1.parseDistributionPayload)(payload);
128
+ const record = {
97
129
  groupId,
98
130
  sender,
99
131
  keyId: parsed.keyId,
100
- timestampMs: Date.now()
101
- })
102
- ]);
103
- return record;
104
- }
105
- async encryptGroupMessage(groupId, sender, plaintext) {
106
- const senderKey = await this.ensureSenderKey(groupId, sender);
107
- if (!senderKey.signingPrivateKey) {
108
- throw new Error('sender private signing key is missing');
109
- }
110
- const derived = await (0, SenderKeyChain_1.deriveSenderKeyMsgKey)(senderKey.iteration, senderKey.chainKey);
111
- const messagePayload = await aesCbcEncryptFromSeed(derived.messageKey.seed, plaintext);
112
- const senderKeyMessage = _proto_1.proto.SenderKeyMessage.encode({
113
- id: senderKey.keyId,
114
- iteration: derived.messageKey.iteration,
115
- ciphertext: messagePayload
116
- }).finish();
117
- const versionedContent = (0, _crypto_1.prependVersion)(senderKeyMessage, constants_1.SIGNAL_GROUP_VERSION);
118
- const signature = await (0, WaAdvSignature_1.signSignalMessage)(senderKey.signingPrivateKey, versionedContent);
119
- if (signature.length !== constants_1.SIGNATURE_SIZE) {
120
- throw new Error(`invalid sender key signature length ${signature.length}`);
121
- }
122
- const ciphertext = (0, bytes_1.concatBytes)([versionedContent, signature]);
123
- await this.store.upsertSenderKey({
124
- ...senderKey,
125
- chainKey: derived.nextChainKey,
126
- iteration: derived.messageKey.iteration + 1
132
+ iteration: parsed.iteration,
133
+ chainKey: parsed.chainKey,
134
+ signingPublicKey: parsed.signingPublicKey,
135
+ unusedMessageKeys: []
136
+ };
137
+ await Promise.all([
138
+ this.store.upsertSenderKey(record),
139
+ this.store.upsertSenderKeyDistribution({
140
+ groupId,
141
+ sender,
142
+ keyId: parsed.keyId,
143
+ timestampMs: Date.now()
144
+ })
145
+ ]);
146
+ return record;
127
147
  });
128
- return {
129
- groupId,
130
- sender,
131
- keyId: senderKey.keyId,
132
- iteration: derived.messageKey.iteration,
133
- ciphertext
134
- };
135
148
  }
136
149
  async decryptGroupMessage(payload) {
137
- const parsed = (0, SenderKeyCodec_1.parseSenderKeyMessage)(payload.ciphertext);
138
- const senderKey = await this.store.getDeviceSenderKey(payload.groupId, payload.sender);
139
- if (!senderKey) {
140
- throw new Error('missing sender key');
141
- }
142
- if (senderKey.keyId !== parsed.keyId) {
143
- throw new Error('sender key id mismatch');
144
- }
145
- if (payload.keyId !== undefined &&
146
- payload.keyId !== null &&
147
- parsed.keyId !== payload.keyId) {
148
- throw new Error('sender key id mismatch');
149
- }
150
- if (payload.iteration !== undefined &&
151
- payload.iteration !== null &&
152
- parsed.iteration !== payload.iteration) {
153
- throw new Error('sender key iteration mismatch');
154
- }
155
- const signedContent = parsed.versionContentMac.subarray(0, parsed.versionContentMac.length - constants_1.SIGNATURE_SIZE);
156
- const signature = parsed.versionContentMac.subarray(parsed.versionContentMac.length - constants_1.SIGNATURE_SIZE);
157
- const validSignature = await (0, WaAdvSignature_1.verifySignalSignature)(senderKey.signingPublicKey, signedContent, signature);
158
- if (!validSignature) {
159
- throw new Error('invalid sender key signature');
160
- }
161
- const selected = await (0, SenderKeyChain_1.selectMessageKey)(senderKey, parsed.iteration);
162
- const plaintext = await aesCbcDecryptFromSeed(selected.messageKey.seed, parsed.ciphertext);
163
- await this.store.upsertSenderKey(selected.updatedRecord);
164
- return plaintext;
150
+ return this.runWithSenderLock(payload.groupId, payload.sender, async () => {
151
+ const parsed = (0, SenderKeyCodec_1.parseSenderKeyMessage)(payload.ciphertext);
152
+ const senderKey = await this.store.getDeviceSenderKey(payload.groupId, payload.sender);
153
+ if (!senderKey) {
154
+ throw new Error('missing sender key');
155
+ }
156
+ if (senderKey.keyId !== parsed.keyId) {
157
+ throw new Error('sender key id mismatch');
158
+ }
159
+ if (payload.keyId !== undefined &&
160
+ payload.keyId !== null &&
161
+ parsed.keyId !== payload.keyId) {
162
+ throw new Error('sender key id mismatch');
163
+ }
164
+ if (payload.iteration !== undefined &&
165
+ payload.iteration !== null &&
166
+ parsed.iteration !== payload.iteration) {
167
+ throw new Error('sender key iteration mismatch');
168
+ }
169
+ const signedContent = parsed.versionContentMac.subarray(0, parsed.versionContentMac.length - constants_1.SIGNAL_SIGNATURE_LENGTH);
170
+ const signature = parsed.versionContentMac.subarray(parsed.versionContentMac.length - constants_1.SIGNAL_SIGNATURE_LENGTH);
171
+ const validSignature = await (0, WaAdvSignature_1.verifySignalSignature)(senderKey.signingPublicKey, signedContent, signature);
172
+ if (!validSignature) {
173
+ throw new Error('invalid sender key signature');
174
+ }
175
+ const selected = await (0, SenderKeyChain_1.selectMessageKey)(senderKey, parsed.iteration);
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
+ });
165
181
  }
166
- async ensureSenderKey(groupId, sender) {
182
+ async ensureSenderKeyInternal(groupId, sender) {
167
183
  const existing = await this.store.getDeviceSenderKey(groupId, sender);
168
184
  if (existing) {
169
185
  return existing;
@@ -186,5 +202,8 @@ class SenderKeyManager {
186
202
  await this.store.upsertSenderKey(created);
187
203
  return created;
188
204
  }
205
+ runWithSenderLock(groupId, sender, task) {
206
+ return this.senderLock.run(`senderKey:${groupId}:${(0, jid_1.signalAddressKey)(sender)}`, task);
207
+ }
189
208
  }
190
209
  exports.SenderKeyManager = SenderKeyManager;
@@ -1,6 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSignalSessionResolver = exports.SignalProtocol = exports.createAndStoreInitialKeys = exports.SenderKeyManager = exports.SignalSessionSyncApi = exports.SignalRotateKeyApi = exports.SignalMissingPreKeysSyncApi = exports.SignalIdentitySyncApi = exports.SignalDeviceSyncApi = exports.SignalDigestSyncApi = exports.parsePreKeyUploadFailure = exports.buildPreKeyUploadIq = exports.generateSignedPreKey = exports.generateRegistrationInfo = exports.generateRegistrationId = exports.generatePreKeyPair = void 0;
3
+ exports.createSignalSessionResolver = exports.SignalProtocol = exports.createAndStoreInitialKeys = exports.SenderKeyManager = exports.SignalSessionSyncApi = exports.SignalRotateKeyApi = exports.SignalMissingPreKeysSyncApi = exports.SignalIdentitySyncApi = exports.SignalDeviceSyncApi = exports.SignalDigestSyncApi = exports.parsePreKeyUploadFailure = exports.buildPreKeyUploadIq = exports.generateSignedPreKey = exports.generateRegistrationInfo = exports.generateRegistrationId = exports.generatePreKeyPair = exports.toSignalAddressParts = exports.encodeSignalSessionRecord = exports.encodeSenderKeyRecord = exports.decodeStoreCount = exports.decodeSenderKeyRecord = exports.decodeSenderKeyDistributionRow = exports.decodeSignalSignedPreKeyRow = exports.decodeSignalSessionRecord = exports.decodeSignalRemoteIdentity = exports.decodeSignalRegistrationRow = exports.decodeSignalPreKeyRow = void 0;
4
+ var encoding_1 = require("./encoding");
5
+ Object.defineProperty(exports, "decodeSignalPreKeyRow", { enumerable: true, get: function () { return encoding_1.decodeSignalPreKeyRow; } });
6
+ Object.defineProperty(exports, "decodeSignalRegistrationRow", { enumerable: true, get: function () { return encoding_1.decodeSignalRegistrationRow; } });
7
+ Object.defineProperty(exports, "decodeSignalRemoteIdentity", { enumerable: true, get: function () { return encoding_1.decodeSignalRemoteIdentity; } });
8
+ Object.defineProperty(exports, "decodeSignalSessionRecord", { enumerable: true, get: function () { return encoding_1.decodeSignalSessionRecord; } });
9
+ Object.defineProperty(exports, "decodeSignalSignedPreKeyRow", { enumerable: true, get: function () { return encoding_1.decodeSignalSignedPreKeyRow; } });
10
+ Object.defineProperty(exports, "decodeSenderKeyDistributionRow", { enumerable: true, get: function () { return encoding_1.decodeSenderKeyDistributionRow; } });
11
+ Object.defineProperty(exports, "decodeSenderKeyRecord", { enumerable: true, get: function () { return encoding_1.decodeSenderKeyRecord; } });
12
+ Object.defineProperty(exports, "decodeStoreCount", { enumerable: true, get: function () { return encoding_1.decodeStoreCount; } });
13
+ Object.defineProperty(exports, "encodeSenderKeyRecord", { enumerable: true, get: function () { return encoding_1.encodeSenderKeyRecord; } });
14
+ Object.defineProperty(exports, "encodeSignalSessionRecord", { enumerable: true, get: function () { return encoding_1.encodeSignalSessionRecord; } });
15
+ Object.defineProperty(exports, "toSignalAddressParts", { enumerable: true, get: function () { return encoding_1.toSignalAddressParts; } });
4
16
  var keygen_1 = require("./registration/keygen");
5
17
  Object.defineProperty(exports, "generatePreKeyPair", { enumerable: true, get: function () { return keygen_1.generatePreKeyPair; } });
6
18
  Object.defineProperty(exports, "generateRegistrationId", { enumerable: true, get: function () { return keygen_1.generateRegistrationId; } });
@@ -9,9 +9,13 @@ const keys_1 = require("../../crypto/core/keys");
9
9
  const X25519_1 = require("../../crypto/curves/X25519");
10
10
  const WaAdvSignature_1 = require("../crypto/WaAdvSignature");
11
11
  async function generateRegistrationInfo() {
12
+ const [registrationId, identityKeyPair] = await Promise.all([
13
+ generateRegistrationId(),
14
+ X25519_1.X25519.generateKeyPair()
15
+ ]);
12
16
  return {
13
- registrationId: await generateRegistrationId(),
14
- identityKeyPair: await X25519_1.X25519.generateKeyPair()
17
+ registrationId,
18
+ identityKeyPair
15
19
  };
16
20
  }
17
21
  async function generatePreKeyPair(keyId) {
@@ -8,6 +8,7 @@ async function createAndStoreInitialKeys(store) {
8
8
  (0, keygen_1.generatePreKeyPair)(1)
9
9
  ]);
10
10
  const signedPreKey = await (0, keygen_1.generateSignedPreKey)(1, registrationInfo.identityKeyPair.privKey);
11
+ // Keep writes ordered so partial commit failures don't leave split registration bootstrap state.
11
12
  await store.setRegistrationInfo(registrationInfo);
12
13
  await store.setSignedPreKey(signedPreKey);
13
14
  await store.getOrGenSinglePreKey(async () => firstPreKey);