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
@@ -1,4 +1,4 @@
1
- import { buildCommsConfig, loadOrCreateCredentials, persistCredentials } from './flow/WaAuthCredentialsFlow.js';
1
+ import { buildCommsConfig, loadOrCreateCredentials, persistCredentials } from './credentials-flow.js';
2
2
  import { WaPairingFlow } from './pairing/WaPairingFlow.js';
3
3
  import { WaQrFlow } from './pairing/WaQrFlow.js';
4
4
  import { getWaCompanionPlatformId, WA_DEFAULTS } from '../protocol/constants.js';
@@ -24,6 +24,7 @@ export class WaAuthClient {
24
24
  this.callbacks = deps.callbacks ?? {};
25
25
  this.authStore = deps.authStore;
26
26
  this.signalStore = deps.signalStore;
27
+ this.preKeyStore = deps.preKeyStore;
27
28
  this.credentials = null;
28
29
  this.qrFlow = new WaQrFlow({
29
30
  logger: this.logger,
@@ -44,13 +45,14 @@ export class WaAuthClient {
44
45
  emitPairingCode: (code) => this.callbacks.onPairingCode?.(code),
45
46
  emitPairingRefresh: (forceManual) => this.callbacks.onPairingRefresh?.(forceManual),
46
47
  emitPaired: (credentials) => this.callbacks.onPaired?.(credentials)
47
- }
48
+ },
49
+ dangerous: options.dangerous
48
50
  });
49
51
  }
50
52
  getState(connected = false) {
51
53
  return {
52
54
  connected,
53
- registered: hasMeJid(this.credentials),
55
+ registered: this.credentials?.meJid !== null && this.credentials?.meJid !== undefined,
54
56
  hasQr: this.qrFlow.hasQr(),
55
57
  hasPairingCode: this.pairingFlow.hasPairingSession()
56
58
  };
@@ -64,20 +66,27 @@ export class WaAuthClient {
64
66
  this.credentials = await loadOrCreateCredentials({
65
67
  logger: this.logger,
66
68
  authStore: this.authStore,
67
- signalStore: this.signalStore
69
+ signalStore: this.signalStore,
70
+ preKeyStore: this.preKeyStore,
71
+ skipSignedPreKeySignatureVerification: this.options.dangerous?.disableSignedPreKeySignatureVerification
68
72
  });
69
73
  this.logger.info('auth client credentials ready', {
70
- registered: hasMeJid(this.credentials)
74
+ registered: this.credentials?.meJid !== null && this.credentials?.meJid !== undefined
71
75
  });
72
76
  return this.credentials;
73
77
  });
74
78
  }
75
- buildCommsConfig(socketOptions) {
79
+ buildCommsConfig(socketOptions, overrides = {}) {
76
80
  this.logger.trace('auth client building comms config');
77
81
  return buildCommsConfig(this.logger, this.requireCredentials(), socketOptions, {
78
82
  deviceBrowser: this.options.deviceBrowser,
79
83
  deviceOsDisplayName: this.options.deviceOsDisplayName,
80
- requireFullSync: this.options.requireFullSync
84
+ requireFullSync: this.options.requireFullSync,
85
+ version: this.options.version,
86
+ mobileTransport: this.options.mobileTransport,
87
+ noiseTrustedRootCa: overrides.noiseTrustedRootCa,
88
+ disableNoiseCertificateChainVerification: overrides.disableNoiseCertificateChainVerification ??
89
+ this.options.dangerous?.disableNoiseCertificateChainVerification
81
90
  });
82
91
  }
83
92
  async clearTransientState() {
@@ -87,9 +96,8 @@ export class WaAuthClient {
87
96
  }
88
97
  async clearStoredCredentials() {
89
98
  this.logger.warn('auth client clearing stored credentials');
90
- await this.authStore.clear();
91
99
  this.credentials = null;
92
- await this.clearTransientState();
100
+ await Promise.all([this.authStore.clear(), this.clearTransientState()]);
93
101
  }
94
102
  async persistServerStaticKey(serverStaticKey) {
95
103
  this.logger.debug('persisting server static key', {
@@ -142,53 +150,45 @@ export class WaAuthClient {
142
150
  });
143
151
  }
144
152
  async persistSuccessAttributes(attributes) {
145
- await this.patchCredentials((credentials) => {
146
- return {
147
- ...credentials,
148
- meLid: attributes.meLid ?? credentials.meLid,
149
- meDisplayName: attributes.meDisplayName ?? credentials.meDisplayName,
150
- companionEncStatic: attributes.companionEncStatic ?? credentials.companionEncStatic,
151
- lastSuccessTs: attributes.lastSuccessTs ?? credentials.lastSuccessTs,
152
- propsVersion: attributes.propsVersion ?? credentials.propsVersion,
153
- abPropsVersion: attributes.abPropsVersion ?? credentials.abPropsVersion,
154
- connectionLocation: attributes.connectionLocation ?? credentials.connectionLocation,
155
- accountCreationTs: attributes.accountCreationTs ?? credentials.accountCreationTs
156
- };
157
- }, {
158
- shouldPersist: (current, next) => next.meLid !== current.meLid ||
159
- next.meDisplayName !== current.meDisplayName ||
160
- (current.companionEncStatic === undefined) !==
161
- (next.companionEncStatic === undefined) ||
153
+ let persistDiff;
154
+ const computeDiff = (current, next) => ({
155
+ lidChanged: next.meLid !== current.meLid,
156
+ displayNameChanged: next.meDisplayName !== current.meDisplayName,
157
+ companionChanged: (current.companionEncStatic === undefined) !==
158
+ (next.companionEncStatic === undefined) ||
162
159
  (current.companionEncStatic !== undefined &&
163
160
  next.companionEncStatic !== undefined &&
164
- !uint8Equal(current.companionEncStatic, next.companionEncStatic)) ||
165
- next.lastSuccessTs !== current.lastSuccessTs ||
166
- next.propsVersion !== current.propsVersion ||
167
- next.abPropsVersion !== current.abPropsVersion ||
168
- next.connectionLocation !== current.connectionLocation ||
169
- next.accountCreationTs !== current.accountCreationTs,
170
- onPersist: (current, next) => {
171
- this.logger.debug('persisting success attributes', {
172
- lidChanged: next.meLid !== current.meLid,
173
- displayNameChanged: next.meDisplayName !== current.meDisplayName,
174
- companionChanged: (current.companionEncStatic === undefined) !==
175
- (next.companionEncStatic === undefined) ||
176
- (current.companionEncStatic !== undefined &&
177
- next.companionEncStatic !== undefined &&
178
- !uint8Equal(current.companionEncStatic, next.companionEncStatic)),
179
- lastSuccessTsChanged: next.lastSuccessTs !== current.lastSuccessTs,
180
- propsVersionChanged: next.propsVersion !== current.propsVersion,
181
- abPropsVersionChanged: next.abPropsVersion !== current.abPropsVersion,
182
- connectionLocationChanged: next.connectionLocation !== current.connectionLocation,
183
- accountCreationTsChanged: next.accountCreationTs !== current.accountCreationTs
184
- });
161
+ !uint8Equal(current.companionEncStatic, next.companionEncStatic)),
162
+ lastSuccessTsChanged: next.lastSuccessTs !== current.lastSuccessTs,
163
+ propsVersionChanged: next.propsVersion !== current.propsVersion,
164
+ abPropsVersionChanged: next.abPropsVersion !== current.abPropsVersion,
165
+ connectionLocationChanged: next.connectionLocation !== current.connectionLocation,
166
+ accountCreationTsChanged: next.accountCreationTs !== current.accountCreationTs
167
+ });
168
+ await this.patchCredentials((credentials) => ({
169
+ ...credentials,
170
+ meLid: attributes.meLid ?? credentials.meLid,
171
+ meDisplayName: attributes.meDisplayName ?? credentials.meDisplayName,
172
+ companionEncStatic: attributes.companionEncStatic ?? credentials.companionEncStatic,
173
+ lastSuccessTs: attributes.lastSuccessTs ?? credentials.lastSuccessTs,
174
+ propsVersion: attributes.propsVersion ?? credentials.propsVersion,
175
+ abPropsVersion: attributes.abPropsVersion ?? credentials.abPropsVersion,
176
+ connectionLocation: attributes.connectionLocation ?? credentials.connectionLocation,
177
+ accountCreationTs: attributes.accountCreationTs ?? credentials.accountCreationTs
178
+ }), {
179
+ shouldPersist: (current, next) => {
180
+ persistDiff = computeDiff(current, next);
181
+ return Object.values(persistDiff).some(Boolean);
182
+ },
183
+ onPersist: () => {
184
+ this.logger.debug('persisting success attributes', persistDiff);
185
185
  }
186
186
  });
187
187
  }
188
- async requestPairingCode(phoneNumber, shouldShowPushNotification = false) {
188
+ async requestPairingCode(phoneNumber, shouldShowPushNotification = false, customCode) {
189
189
  this.requireCredentials();
190
190
  this.logger.info('auth client requesting pairing code');
191
- return this.runHandled(() => this.pairingFlow.requestPairingCode(phoneNumber, shouldShowPushNotification));
191
+ return this.runHandled(() => this.pairingFlow.requestPairingCode(phoneNumber, shouldShowPushNotification, customCode));
192
192
  }
193
193
  async fetchPairingCountryCodeIso() {
194
194
  this.requireCredentials();
@@ -230,13 +230,14 @@ export class WaAuthClient {
230
230
  }
231
231
  async updateCredentials(credentials) {
232
232
  this.logger.trace('auth client update credentials', {
233
- registered: hasMeJid(credentials)
233
+ registered: credentials?.meJid !== null && credentials?.meJid !== undefined
234
234
  });
235
235
  this.credentials = credentials;
236
236
  await persistCredentials({
237
237
  logger: this.logger,
238
238
  authStore: this.authStore,
239
- signalStore: this.signalStore
239
+ signalStore: this.signalStore,
240
+ preKeyStore: this.preKeyStore
240
241
  }, credentials);
241
242
  }
242
243
  requireCredentials() {
@@ -250,6 +251,3 @@ export class WaAuthClient {
250
251
  this.callbacks.onError?.(error);
251
252
  }
252
253
  }
253
- function hasMeJid(credentials) {
254
- return credentials?.meJid !== null && credentials?.meJid !== undefined;
255
- }
@@ -0,0 +1,190 @@
1
+ import { randomBytesAsync, toRawPubKey, xeddsaVerify } from '../crypto/index.js';
2
+ import { toSerializedPubKey } from '../crypto/core/keys.js';
3
+ import { X25519 } from '../crypto/curves/X25519.js';
4
+ import { getLoginIdentity } from '../protocol/jid.js';
5
+ import { createAndStoreInitialKeys } from '../signal/registration/utils.js';
6
+ import { WaMobileTcpSocketCtor } from '../transport/node/WaMobileTcpSocket.js';
7
+ import { buildMobileLoginPayload } from '../transport/noise/WaMobileClientPayload.js';
8
+ import { toProxyAgent, toProxyDispatcher } from '../transport/proxy.js';
9
+ import { toError } from '../util/primitives.js';
10
+ export async function loadOrCreateCredentials(args) {
11
+ args.logger.trace('auth credentials loadOrCreate start');
12
+ const existing = await args.authStore.load();
13
+ if (!existing) {
14
+ const credentials = await createFreshAndPersistCredentials(args);
15
+ args.logger.info('created fresh auth credentials');
16
+ return credentials;
17
+ }
18
+ args.logger.debug('auth credentials loaded from store', {
19
+ registered: existing.meJid !== null && existing.meJid !== undefined,
20
+ hasServerStaticKey: existing.serverStaticKey !== null && existing.serverStaticKey !== undefined
21
+ });
22
+ const skipSignedPreKeyCheck = args.skipSignedPreKeySignatureVerification === true;
23
+ if (!existing.meJid &&
24
+ !skipSignedPreKeyCheck &&
25
+ !(await hasValidSignedPreKey(args.logger, existing))) {
26
+ args.logger.warn('signed pre-key is invalid, regenerating credentials');
27
+ const fresh = await createFreshAndPersistCredentials(args);
28
+ args.logger.info('regenerated credentials due to invalid signed pre-key');
29
+ return fresh;
30
+ }
31
+ await restoreSignalStore(args.signalStore, args.preKeyStore, existing);
32
+ args.logger.trace('auth credentials restored into signal store');
33
+ return existing;
34
+ }
35
+ export async function persistCredentials(args, credentials) {
36
+ args.logger.trace('persisting auth credentials', {
37
+ registered: credentials.meJid !== null && credentials.meJid !== undefined
38
+ });
39
+ await args.authStore.save(credentials);
40
+ }
41
+ function mobileTransportFromCredentials(credentials) {
42
+ if (!credentials.deviceInfo)
43
+ return undefined;
44
+ return {
45
+ deviceInfo: credentials.deviceInfo,
46
+ ...(credentials.pushName !== undefined ? { pushName: credentials.pushName } : {}),
47
+ ...(credentials.yearClass !== undefined ? { yearClass: credentials.yearClass } : {}),
48
+ ...(credentials.memClass !== undefined ? { memClass: credentials.memClass } : {})
49
+ };
50
+ }
51
+ export function buildCommsConfig(logger, credentials, socketOptions, clientOptions) {
52
+ const meJid = credentials.meJid;
53
+ const registered = meJid !== null && meJid !== undefined;
54
+ const loginIdentity = registered ? getLoginIdentity(meJid) : null;
55
+ const wsProxy = socketOptions.proxy?.ws;
56
+ // Resolve the effective mobile transport: explicit option wins, otherwise
57
+ // synthesize one from persisted credentials.deviceInfo so a registered
58
+ // mobile session boots in mobile mode without the caller re-passing
59
+ // deviceInfo on every `new WaClient(...)` call.
60
+ const effectiveMobileTransport = clientOptions.mobileTransport ?? mobileTransportFromCredentials(credentials);
61
+ logger.debug('building comms config from credentials', {
62
+ registered,
63
+ hasServerStaticKey: credentials.serverStaticKey !== null && credentials.serverStaticKey !== undefined,
64
+ mobile: Boolean(effectiveMobileTransport),
65
+ mobileSource: clientOptions.mobileTransport
66
+ ? 'option'
67
+ : effectiveMobileTransport
68
+ ? 'credentials'
69
+ : 'none'
70
+ });
71
+ if (effectiveMobileTransport) {
72
+ if (wsProxy) {
73
+ throw new Error('mobileTransport does not support socketOptions.proxy.ws — remove the proxy option or open an issue to add TCP proxy support');
74
+ }
75
+ if (!loginIdentity) {
76
+ throw new Error('mobileTransport requires registered credentials (meJid) — run the mobile bridge flow first');
77
+ }
78
+ const loginPayload = buildMobileLoginPayload({
79
+ username: loginIdentity.username,
80
+ device: loginIdentity.device,
81
+ passive: effectiveMobileTransport.passive ?? false,
82
+ deviceInfo: effectiveMobileTransport.deviceInfo,
83
+ pushName: effectiveMobileTransport.pushName,
84
+ yearClass: effectiveMobileTransport.yearClass,
85
+ memClass: effectiveMobileTransport.memClass
86
+ });
87
+ return {
88
+ url: effectiveMobileTransport.tcpUrl ?? 'tcp://g.whatsapp.net:443',
89
+ rawWebSocketConstructor: WaMobileTcpSocketCtor,
90
+ connectTimeoutMs: socketOptions.connectTimeoutMs,
91
+ reconnectIntervalMs: socketOptions.reconnectIntervalMs,
92
+ timeoutIntervalMs: socketOptions.timeoutIntervalMs,
93
+ maxReconnectAttempts: socketOptions.maxReconnectAttempts,
94
+ noise: {
95
+ clientStaticKeyPair: credentials.noiseKeyPair,
96
+ isRegistered: true,
97
+ serverStaticKey: credentials.serverStaticKey,
98
+ routingInfo: credentials.routingInfo,
99
+ trustedRootCa: clientOptions.noiseTrustedRootCa,
100
+ verifyCertificateChain: clientOptions.disableNoiseCertificateChainVerification
101
+ ? false
102
+ : undefined,
103
+ loginPayload
104
+ }
105
+ };
106
+ }
107
+ return {
108
+ url: socketOptions.url,
109
+ urls: socketOptions.urls,
110
+ protocols: socketOptions.protocols,
111
+ dispatcher: toProxyDispatcher(wsProxy),
112
+ agent: toProxyAgent(wsProxy),
113
+ connectTimeoutMs: socketOptions.connectTimeoutMs,
114
+ reconnectIntervalMs: socketOptions.reconnectIntervalMs,
115
+ timeoutIntervalMs: socketOptions.timeoutIntervalMs,
116
+ maxReconnectAttempts: socketOptions.maxReconnectAttempts,
117
+ noise: {
118
+ clientStaticKeyPair: credentials.noiseKeyPair,
119
+ isRegistered: registered,
120
+ serverStaticKey: credentials.serverStaticKey,
121
+ routingInfo: credentials.routingInfo,
122
+ trustedRootCa: clientOptions.noiseTrustedRootCa,
123
+ verifyCertificateChain: clientOptions.disableNoiseCertificateChainVerification
124
+ ? false
125
+ : undefined,
126
+ loginPayloadConfig: loginIdentity
127
+ ? {
128
+ username: loginIdentity.username,
129
+ device: loginIdentity.device,
130
+ deviceBrowser: clientOptions.deviceBrowser,
131
+ deviceOsDisplayName: clientOptions.deviceOsDisplayName,
132
+ versionBase: clientOptions.version
133
+ }
134
+ : undefined,
135
+ registrationPayloadConfig: !loginIdentity
136
+ ? {
137
+ registrationInfo: credentials.registrationInfo,
138
+ signedPreKey: credentials.signedPreKey,
139
+ deviceBrowser: clientOptions.deviceBrowser,
140
+ deviceOsDisplayName: clientOptions.deviceOsDisplayName,
141
+ requireFullSync: clientOptions.requireFullSync,
142
+ versionBase: clientOptions.version
143
+ }
144
+ : undefined
145
+ }
146
+ };
147
+ }
148
+ async function createFreshCredentials(signalStore, preKeyStore, logger) {
149
+ logger.trace('creating fresh credentials');
150
+ const [noiseKeyPair, registrationBundle, advSecretKey] = await Promise.all([
151
+ X25519.generateKeyPair(),
152
+ createAndStoreInitialKeys(signalStore, preKeyStore),
153
+ randomBytesAsync(32)
154
+ ]);
155
+ return {
156
+ noiseKeyPair,
157
+ registrationInfo: registrationBundle.registrationInfo,
158
+ signedPreKey: registrationBundle.signedPreKey,
159
+ serverHasPreKeys: false,
160
+ advSecretKey
161
+ };
162
+ }
163
+ async function createFreshAndPersistCredentials(args) {
164
+ const credentials = await createFreshCredentials(args.signalStore, args.preKeyStore, args.logger);
165
+ // Persist credentials first so signal restore never commits state for credentials that failed to save.
166
+ await args.authStore.save(credentials);
167
+ await restoreSignalStore(args.signalStore, args.preKeyStore, credentials);
168
+ return credentials;
169
+ }
170
+ async function hasValidSignedPreKey(logger, credentials) {
171
+ try {
172
+ const serializedPubKey = toSerializedPubKey(credentials.signedPreKey.keyPair.pubKey);
173
+ const valid = await xeddsaVerify(toRawPubKey(credentials.registrationInfo.identityKeyPair.pubKey), serializedPubKey, credentials.signedPreKey.signature);
174
+ logger.trace('signed pre-key validation completed', { valid });
175
+ return valid;
176
+ }
177
+ catch (error) {
178
+ logger.warn('signed pre-key validation failed with exception', {
179
+ message: toError(error).message
180
+ });
181
+ return false;
182
+ }
183
+ }
184
+ async function restoreSignalStore(signalStore, preKeyStore, credentials) {
185
+ await Promise.all([
186
+ signalStore.setRegistrationInfo(credentials.registrationInfo),
187
+ signalStore.setSignedPreKey(credentials.signedPreKey),
188
+ preKeyStore.setServerHasPreKeys(credentials.serverHasPreKeys === true)
189
+ ]);
190
+ }
@@ -1,4 +1,2 @@
1
1
  export * from './types.js';
2
2
  export { WaAuthClient } from './WaAuthClient.js';
3
- export { completeCompanionFinish, createCompanionHello } from './pairing/WaPairingCodeCrypto.js';
4
- export { WaAuthSqliteStore } from '../store/providers/sqlite/auth.store.js';
@@ -1,13 +1,14 @@
1
- import { completeCompanionFinish, createCompanionHello } from '../pairing/WaPairingCodeCrypto.js';
1
+ import { completeCompanionFinish, createCompanionHello, normalizeCustomPairingCode } from '../pairing/pairing-code-crypto.js';
2
2
  import { randomBytesAsync } from '../../crypto/index.js';
3
3
  import { proto } from '../../proto.js';
4
+ import { getWaBrowserDisplayName } from '../../protocol/browser.js';
4
5
  import { WA_DEFAULTS, WA_IQ_TYPES, WA_NODE_TAGS, WA_SIGNALING } from '../../protocol/constants.js';
5
6
  import { parsePhoneJid } from '../../protocol/jid.js';
6
7
  import { ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE, computeAdvIdentityHmac, generateDeviceSignature, verifyDeviceIdentityAccountSignature } from '../../signal/crypto/WaAdvSignature.js';
7
- import { buildCompanionFinishRequestNode, buildCompanionHelloRequestNode, buildGetCountryCodeRequestNode, buildIqResultNode, buildNotificationAckNode } from '../../transport/node/builders/pairing.js';
8
- import { decodeNodeContentUtf8OrBytes, findNodeChildrenByTags, findNodeChild, getFirstNodeChild, getNodeChildrenNonEmptyUtf8ByTag, hasNodeChild } from '../../transport/node/helpers.js';
9
- import { decodeProtoBytes } from '../../util/bytes.js';
10
- import { concatBytes, uint8Equal } from '../../util/bytes.js';
8
+ import { buildAckNode, buildIqResultNode } from '../../transport/node/builders/global.js';
9
+ import { buildCompanionFinishRequestNode, buildCompanionHelloRequestNode, buildGetCountryCodeRequestNode } from '../../transport/node/builders/pairing.js';
10
+ import { decodeNodeContentUtf8OrBytes, findNodeChild, findNodeChildrenByTags, getFirstNodeChild, getNodeChildrenNonEmptyUtf8ByTag, hasNodeChild } from '../../transport/node/helpers.js';
11
+ import { concatBytes, decodeProtoBytes, uint8Equal } from '../../util/bytes.js';
11
12
  export class WaPairingFlow {
12
13
  constructor(options) {
13
14
  this.opts = options;
@@ -20,26 +21,19 @@ export class WaPairingFlow {
20
21
  this.opts.logger.trace('pairing flow session cleared');
21
22
  this.pairingSession = null;
22
23
  }
23
- async requestPairingCode(phoneNumber, shouldShowPushNotification = false) {
24
+ async requestPairingCode(phoneNumber, shouldShowPushNotification = false, customCode) {
24
25
  this.opts.logger.info('requesting pairing code', {
25
- shouldShowPushNotification
26
+ shouldShowPushNotification,
27
+ hasCustomCode: customCode !== undefined
26
28
  });
29
+ const normalizedCustomCode = customCode !== undefined ? normalizeCustomPairingCode(customCode) : undefined;
27
30
  const credentials = this.requireCredentials();
28
31
  const phoneJid = parsePhoneJid(phoneNumber);
29
32
  const [companionHello, refreshedCredentials] = await Promise.all([
30
- createCompanionHello(),
33
+ createCompanionHello({ customCode: normalizedCustomCode }),
31
34
  this.rotateAdvSecret(credentials)
32
35
  ]);
33
- const browser = this.opts.device.browser;
34
- const browserDisplayName = {
35
- chrome: 'Chrome',
36
- firefox: 'Firefox',
37
- ie: 'IE',
38
- opera: 'Opera',
39
- safari: 'Safari',
40
- edge: 'Edge',
41
- chromium: 'Chromium'
42
- }[browser.trim().toLowerCase()] ?? browser;
36
+ const browserDisplayName = getWaBrowserDisplayName(this.opts.device.browser);
43
37
  const response = await this.opts.socket.query(buildCompanionHelloRequestNode({
44
38
  phoneJid,
45
39
  shouldShowPushNotification,
@@ -118,7 +112,10 @@ export class WaPairingFlow {
118
112
  id: node.attrs.id,
119
113
  stage: linkCodeNode.attrs.stage
120
114
  });
121
- await this.opts.socket.sendNode(buildNotificationAckNode(node));
115
+ await this.opts.socket.sendNode(buildAckNode({
116
+ kind: 'notification',
117
+ node
118
+ }));
122
119
  const stage = linkCodeNode.attrs.stage;
123
120
  if (stage === WA_SIGNALING.LINK_CODE_STAGE_REFRESH_CODE) {
124
121
  const refNode = findNodeChild(linkCodeNode, WA_NODE_TAGS.LINK_CODE_PAIRING_REF);
@@ -146,18 +143,24 @@ export class WaPairingFlow {
146
143
  if (!hasExpectedChild) {
147
144
  return false;
148
145
  }
149
- await this.opts.socket.sendNode(buildNotificationAckNode(node, WA_SIGNALING.COMPANION_REG_REFRESH_NOTIFICATION));
146
+ // Rotate first so we don't ack success before local credential state is durably updated.
150
147
  await this.rotateAdvSecret(this.requireCredentials());
148
+ await this.opts.socket.sendNode(buildAckNode({
149
+ kind: 'notification',
150
+ node,
151
+ typeOverride: WA_SIGNALING.COMPANION_REG_REFRESH_NOTIFICATION
152
+ }));
151
153
  this.opts.logger.info('handled companion_reg_refresh notification');
152
154
  this.opts.qrFlow.refreshCurrentQr();
153
155
  return true;
154
156
  }
155
157
  async handlePairDevice(iqNode, pairDeviceNode) {
156
158
  const refs = getNodeChildrenNonEmptyUtf8ByTag(pairDeviceNode, WA_NODE_TAGS.REF, 'pair-device.ref');
159
+ // Commit adv-secret rotation before sending IQ success to avoid protocol/state divergence.
157
160
  await this.rotateAdvSecret(this.requireCredentials());
161
+ await this.opts.socket.sendNode(buildIqResultNode(iqNode));
158
162
  this.opts.qrFlow.setRefs(refs);
159
163
  this.opts.logger.info('pair-device refs updated', { refsCount: refs.length });
160
- await this.opts.socket.sendNode(buildIqResultNode(iqNode));
161
164
  }
162
165
  async handlePairSuccess(iqNode, pairSuccessNode) {
163
166
  this.opts.logger.info('processing pair-success node');
@@ -176,13 +179,15 @@ export class WaPairingFlow {
176
179
  const wrappedHmac = decodeProtoBytes(wrappedIdentity.hmac, 'ADVSignedDeviceIdentityHMAC.hmac');
177
180
  const accountType = wrappedIdentity.accountType ?? proto.ADVEncryptionType.E2EE;
178
181
  const isHosted = accountType === proto.ADVEncryptionType.HOSTED;
179
- const hmacInput = isHosted
180
- ? concatBytes([ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE, wrappedDetails])
181
- : wrappedDetails;
182
- const expectedHmac = await computeAdvIdentityHmac(credentials.advSecretKey, hmacInput);
183
- if (!uint8Equal(expectedHmac, wrappedHmac)) {
184
- this.opts.logger.error('pair-success hmac mismatch');
185
- throw new Error('pair-success HMAC validation failed');
182
+ if (this.opts.dangerous?.disablePairSuccessHmacVerification !== true) {
183
+ const hmacInput = isHosted
184
+ ? concatBytes([ADV_PREFIX_HOSTED_ACCOUNT_SIGNATURE, wrappedDetails])
185
+ : wrappedDetails;
186
+ const expectedHmac = await computeAdvIdentityHmac(credentials.advSecretKey, hmacInput);
187
+ if (!uint8Equal(expectedHmac, wrappedHmac)) {
188
+ this.opts.logger.error('pair-success hmac mismatch');
189
+ throw new Error('pair-success HMAC validation failed');
190
+ }
186
191
  }
187
192
  const { signedIdentity, keyIndex, responseIdentityBytes } = await this.buildPairSuccessResponseIdentity(credentials, wrappedDetails, isHosted);
188
193
  const nextCredentials = {
@@ -231,10 +236,12 @@ export class WaPairingFlow {
231
236
  const accountSignature = decodeProtoBytes(signedIdentity.accountSignature, 'ADVSignedDeviceIdentity.accountSignature');
232
237
  const accountSignatureKey = decodeProtoBytes(signedIdentity.accountSignatureKey, 'ADVSignedDeviceIdentity.accountSignatureKey');
233
238
  const localIdentity = credentials.registrationInfo.identityKeyPair;
234
- const validAccountSignature = await verifyDeviceIdentityAccountSignature(details, accountSignature, localIdentity.pubKey, accountSignatureKey, isHosted);
235
- if (!validAccountSignature) {
236
- this.opts.logger.error('pair-success account signature invalid');
237
- throw new Error('pair-success account signature validation failed');
239
+ if (this.opts.dangerous?.disableAdvSignatureVerification !== true) {
240
+ const validAccountSignature = await verifyDeviceIdentityAccountSignature(details, accountSignature, localIdentity.pubKey, accountSignatureKey, isHosted);
241
+ if (!validAccountSignature) {
242
+ this.opts.logger.error('pair-success account signature invalid');
243
+ throw new Error('pair-success account signature validation failed');
244
+ }
238
245
  }
239
246
  signedIdentity.deviceSignature = await generateDeviceSignature(details, localIdentity, accountSignatureKey, isHosted);
240
247
  const advDeviceIdentity = proto.ADVDeviceIdentity.decode(details);
@@ -1,8 +1,9 @@
1
- import { CROCKFORD_ALPHABET, PBKDF2_ITERATIONS } from '../pairing/constants.js';
2
1
  import { aesCtrDecrypt, aesCtrEncrypt, aesGcmEncrypt, hkdf, importAesGcmKey, pbkdf2DeriveAesCtrKey, randomBytesAsync } from '../../crypto/index.js';
3
2
  import { X25519 } from '../../crypto/curves/X25519.js';
4
3
  import { WA_PAIRING_KDF_INFO } from '../../protocol/constants.js';
5
4
  import { concatBytes, TEXT_ENCODER } from '../../util/bytes.js';
5
+ export const CROCKFORD_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTVWXYZ';
6
+ export const PBKDF2_ITERATIONS = 2 << 16;
6
7
  function bytesToCrockford(bytes) {
7
8
  let bitCount = 0;
8
9
  let value = 0;
@@ -20,14 +21,27 @@ function bytesToCrockford(bytes) {
20
21
  }
21
22
  return out;
22
23
  }
23
- export async function createCompanionHello() {
24
- const [codeBytes, companionEphemeralKeyPair, salt, counter] = await Promise.all([
25
- randomBytesAsync(5),
24
+ export function normalizeCustomPairingCode(input) {
25
+ const stripped = input.replace(/-/g, '').toUpperCase();
26
+ if (stripped.length !== 8) {
27
+ throw new Error(`custom pairing code must be 8 characters, got ${stripped.length}`);
28
+ }
29
+ for (let i = 0; i < stripped.length; i += 1) {
30
+ if (CROCKFORD_ALPHABET.indexOf(stripped[i]) < 0) {
31
+ throw new Error(`custom pairing code contains invalid character "${stripped[i]}" (allowed: ${CROCKFORD_ALPHABET})`);
32
+ }
33
+ }
34
+ return stripped;
35
+ }
36
+ export async function createCompanionHello(options = {}) {
37
+ const normalizedCustomCode = options.customCode !== undefined ? normalizeCustomPairingCode(options.customCode) : null;
38
+ const [companionEphemeralKeyPair, salt, counter, codeBytes] = await Promise.all([
26
39
  X25519.generateKeyPair(),
27
40
  randomBytesAsync(32),
28
- randomBytesAsync(16)
41
+ randomBytesAsync(16),
42
+ normalizedCustomCode !== null ? Promise.resolve(null) : randomBytesAsync(5)
29
43
  ]);
30
- const pairingCode = bytesToCrockford(codeBytes);
44
+ const pairingCode = normalizedCustomCode ?? bytesToCrockford(codeBytes);
31
45
  const cipher = await pbkdf2DeriveAesCtrKey(TEXT_ENCODER.encode(pairingCode), salt, PBKDF2_ITERATIONS);
32
46
  const encrypted = await aesCtrEncrypt(cipher, counter, companionEphemeralKeyPair.pubKey);
33
47
  return {
@@ -45,8 +59,8 @@ export async function completeCompanionFinish(args) {
45
59
  if (primaryEphemeralPub.length === 0) {
46
60
  throw new Error('empty primary ephemeral public key');
47
61
  }
48
- const sharedEphemeral = await X25519.scalarMult(args.companionEphemeralPrivKey, primaryEphemeralPub);
49
- const [bundleSalt, bundleSecret, bundleIv] = await Promise.all([
62
+ const [sharedEphemeral, bundleSalt, bundleSecret, bundleIv] = await Promise.all([
63
+ X25519.scalarMult(args.companionEphemeralPrivKey, primaryEphemeralPub),
50
64
  randomBytesAsync(32),
51
65
  randomBytesAsync(32),
52
66
  randomBytesAsync(12)
@@ -58,9 +72,11 @@ export async function completeCompanionFinish(args) {
58
72
  args.primaryIdentityPub,
59
73
  bundleSecret
60
74
  ]);
61
- const encryptedBundle = await aesGcmEncrypt(bundleEncryptionKey, bundleIv, plaintextBundle);
75
+ const [encryptedBundle, sharedIdentity] = await Promise.all([
76
+ aesGcmEncrypt(bundleEncryptionKey, bundleIv, plaintextBundle),
77
+ X25519.scalarMult(args.registrationIdentityKeyPair.privKey, args.primaryIdentityPub)
78
+ ]);
62
79
  const wrappedKeyBundle = concatBytes([bundleSalt, bundleIv, encryptedBundle]);
63
- const sharedIdentity = await X25519.scalarMult(args.registrationIdentityKeyPair.privKey, args.primaryIdentityPub);
64
80
  const advMaterial = concatBytes([sharedEphemeral, sharedIdentity, bundleSecret]);
65
81
  const advSecret = await hkdf(advMaterial, null, WA_PAIRING_KDF_INFO.ADV_SECRET, 32);
66
82
  return {