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
@@ -1,21 +1,20 @@
1
- import { normalizeDeviceJid, splitJid, toUserJid } from '../../protocol/jid.js';
1
+ import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
2
+ import { isHostedDeviceJid, normalizeDeviceJid, splitJid, toUserJid } from '../../protocol/jid.js';
2
3
  import { toError } from '../../util/primitives.js';
3
4
  export function createDeviceFanoutResolver(options) {
4
5
  const { signalDeviceSync, getCurrentMeJid, getCurrentMeLid, logger } = options;
5
- const requireCurrentMeJid = (context) => {
6
- const meJid = getCurrentMeJid();
7
- if (meJid) {
8
- return meJid;
9
- }
10
- throw new Error(`${context} requires registered meJid`);
11
- };
6
+ const dedup = new PromiseDedup();
12
7
  const resolveDirectFanoutDeviceJids = async (recipientJid, selfDeviceJidForRecipient) => {
13
8
  const recipientUserJid = toUserJid(recipientJid);
14
9
  const meUserJid = toUserJid(selfDeviceJidForRecipient);
15
10
  const targets = recipientUserJid === meUserJid ? [recipientUserJid] : [recipientUserJid, meUserJid];
16
11
  try {
17
12
  const synced = await signalDeviceSync.syncDeviceList(targets);
18
- const byUser = new Map(synced.map((entry) => [toUserJid(entry.jid), entry.deviceJids]));
13
+ const byUser = new Map();
14
+ for (let index = 0; index < synced.length; index += 1) {
15
+ const entry = synced[index];
16
+ byUser.set(toUserJid(entry.jid), entry.deviceJids);
17
+ }
19
18
  const fanout = new Set();
20
19
  const recipientDevices = byUser.get(recipientUserJid) ?? [];
21
20
  if (recipientDevices.length === 0) {
@@ -45,7 +44,7 @@ export function createDeviceFanoutResolver(options) {
45
44
  return [recipientUserJid];
46
45
  }
47
46
  };
48
- const resolveGroupParticipantDeviceJids = async (participantUserJids) => {
47
+ const resolveGroupParticipantDeviceJidsInternal = async (participantUserJids) => {
49
48
  const meDeviceJids = new Set();
50
49
  const meJid = getCurrentMeJid();
51
50
  if (meJid) {
@@ -71,7 +70,11 @@ export function createDeviceFanoutResolver(options) {
71
70
  });
72
71
  }
73
72
  }
74
- const candidateUsers = [...new Set(participantUserJids)];
73
+ const candidateUserSet = new Set();
74
+ for (let index = 0; index < participantUserJids.length; index += 1) {
75
+ candidateUserSet.add(participantUserJids[index]);
76
+ }
77
+ const candidateUsers = Array.from(candidateUserSet);
75
78
  if (candidateUsers.length === 0) {
76
79
  return [];
77
80
  }
@@ -89,6 +92,9 @@ export function createDeviceFanoutResolver(options) {
89
92
  }
90
93
  for (const deviceJid of entry.deviceJids) {
91
94
  const normalizedDeviceJid = normalizeDeviceJid(deviceJid);
95
+ if (isHostedDeviceJid(normalizedDeviceJid)) {
96
+ continue;
97
+ }
92
98
  if (meDeviceJids.has(normalizedDeviceJid)) {
93
99
  continue;
94
100
  }
@@ -122,7 +128,10 @@ export function createDeviceFanoutResolver(options) {
122
128
  }
123
129
  };
124
130
  const resolveOwnPeerDeviceJids = async () => {
125
- const meJid = requireCurrentMeJid('resolveOwnPeerDeviceJids');
131
+ const meJid = getCurrentMeJid();
132
+ if (!meJid) {
133
+ throw new Error('resolveOwnPeerDeviceJids requires registered meJid');
134
+ }
126
135
  const meUserJid = toUserJid(meJid);
127
136
  const meDevices = new Set();
128
137
  meDevices.add(normalizeDeviceJid(meJid));
@@ -177,6 +186,7 @@ export function createDeviceFanoutResolver(options) {
177
186
  }
178
187
  return meLid;
179
188
  };
189
+ const resolveGroupParticipantDeviceJids = (participantUserJids) => dedup.run(`group:${participantUserJids.join(',')}`, () => resolveGroupParticipantDeviceJidsInternal(participantUserJids));
180
190
  return {
181
191
  resolveDirectFanoutDeviceJids,
182
192
  resolveGroupParticipantDeviceJids,
@@ -1,7 +1,9 @@
1
+ import { PromiseDedup } from '../../infra/perf/PromiseDedup.js';
1
2
  import { toUserJid } from '../../protocol/jid.js';
2
3
  import { toError } from '../../util/primitives.js';
3
4
  export function createGroupParticipantsCache(options) {
4
5
  const { participantsStore, queryGroupParticipantJids, logger } = options;
6
+ const dedup = new PromiseDedup();
5
7
  const sanitizeParticipantUsers = (participants) => {
6
8
  const deduped = new Set();
7
9
  for (const participant of participants) {
@@ -117,7 +119,7 @@ export function createGroupParticipantsCache(options) {
117
119
  }
118
120
  return sanitizeParticipantUsers(candidates);
119
121
  };
120
- const refreshParticipantUsers = async (groupJid) => {
122
+ const refreshParticipantUsers = (groupJid) => dedup.run(`refresh:${groupJid}`, async () => {
121
123
  const queried = await queryGroupParticipantJids(groupJid);
122
124
  const participants = sanitizeParticipantUsers(queried);
123
125
  await participantsStore.upsertGroupParticipants({
@@ -126,14 +128,14 @@ export function createGroupParticipantsCache(options) {
126
128
  updatedAtMs: Date.now()
127
129
  });
128
130
  return participants;
129
- };
130
- const resolveParticipantUsers = async (groupJid) => {
131
+ });
132
+ const resolveParticipantUsers = (groupJid) => dedup.run(`resolve:${groupJid}`, async () => {
131
133
  const cached = await participantsStore.getGroupParticipants(groupJid);
132
134
  if (cached && cached.participants.length > 0) {
133
135
  return sanitizeParticipantUsers(cached.participants);
134
136
  }
135
137
  return refreshParticipantUsers(groupJid);
136
- };
138
+ });
137
139
  const mutateFromGroupEvent = async (event) => {
138
140
  const groupJid = resolveGroupJidForParticipantCacheEvent(event);
139
141
  if (!groupJid) {
@@ -0,0 +1,125 @@
1
+ import { BackgroundQueue } from '../../infra/perf/BackgroundQueue.js';
2
+ import { toError } from '../../util/primitives.js';
3
+ function mergeThread(previous, incoming) {
4
+ return {
5
+ jid: incoming.jid,
6
+ name: incoming.name ?? previous.name,
7
+ unreadCount: incoming.unreadCount ?? previous.unreadCount,
8
+ archived: incoming.archived ?? previous.archived,
9
+ pinned: incoming.pinned ?? previous.pinned,
10
+ muteEndMs: incoming.muteEndMs ?? previous.muteEndMs,
11
+ markedAsUnread: incoming.markedAsUnread ?? previous.markedAsUnread,
12
+ ephemeralExpiration: incoming.ephemeralExpiration ?? previous.ephemeralExpiration
13
+ };
14
+ }
15
+ function mergeContact(previous, incoming) {
16
+ return {
17
+ jid: incoming.jid,
18
+ displayName: incoming.displayName ?? previous.displayName,
19
+ pushName: incoming.pushName ?? previous.pushName,
20
+ lid: incoming.lid ?? previous.lid,
21
+ phoneNumber: incoming.phoneNumber ?? previous.phoneNumber,
22
+ lastUpdatedMs: Math.max(previous.lastUpdatedMs, incoming.lastUpdatedMs)
23
+ };
24
+ }
25
+ export class WriteBehindPersistence {
26
+ constructor(stores, logger, options = {}) {
27
+ this.logger = logger;
28
+ this.flushTimeoutMs = options.flushTimeoutMs ?? 5000;
29
+ const queueOptions = (domain) => ({
30
+ maxPendingKeys: options.maxPendingKeys ?? 4096,
31
+ maxWriteConcurrency: options.maxWriteConcurrency ?? 4,
32
+ flushTimeoutMs: this.flushTimeoutMs,
33
+ onError: (key, error, attempt) => {
34
+ this.logger.warn('write-behind error', {
35
+ domain,
36
+ key,
37
+ attempt,
38
+ message: toError(error).message
39
+ });
40
+ },
41
+ onPressure: (pendingKeys) => {
42
+ this.logger.warn('write-behind pressure', {
43
+ domain,
44
+ pendingKeys
45
+ });
46
+ },
47
+ onDiscard: (key) => {
48
+ this.logger.warn('write-behind discarded pending write', {
49
+ domain,
50
+ key
51
+ });
52
+ }
53
+ });
54
+ this.queues = {
55
+ messages: new BackgroundQueue((_key, value) => stores.messageStore.upsert(value), queueOptions('messages')),
56
+ threads: new BackgroundQueue((_key, value) => stores.threadStore.upsert(value), {
57
+ ...queueOptions('threads'),
58
+ coalesce: (previous, incoming) => mergeThread(previous, incoming)
59
+ }),
60
+ contacts: new BackgroundQueue((_key, value) => stores.contactStore.upsert(value), {
61
+ ...queueOptions('contacts'),
62
+ coalesce: (previous, incoming) => mergeContact(previous, incoming)
63
+ })
64
+ };
65
+ }
66
+ persistMessage(record) {
67
+ this.queues.messages.enqueue(`msg:${record.id}`, record);
68
+ }
69
+ persistMessageAsync(record) {
70
+ return this.queues.messages.enqueueAsync(`msg:${record.id}`, record);
71
+ }
72
+ persistThread(record) {
73
+ this.queues.threads.enqueue(`thread:${record.jid}`, record);
74
+ }
75
+ persistThreadAsync(record) {
76
+ return this.queues.threads.enqueueAsync(`thread:${record.jid}`, record);
77
+ }
78
+ persistContact(record) {
79
+ this.queues.contacts.enqueue(`contact:${record.jid}`, record);
80
+ }
81
+ persistContactAsync(record) {
82
+ return this.queues.contacts.enqueueAsync(`contact:${record.jid}`, record);
83
+ }
84
+ async flush(timeoutMs = this.flushTimeoutMs) {
85
+ const [messages, threads, contacts] = await Promise.all([
86
+ this.queues.messages.flush(timeoutMs),
87
+ this.queues.threads.flush(timeoutMs),
88
+ this.queues.contacts.flush(timeoutMs)
89
+ ]);
90
+ const result = this.toDrainResult(messages, threads, contacts);
91
+ if (result.remaining > 0) {
92
+ this.logger.warn('write-behind flush finished with pending writes', {
93
+ messagesRemaining: messages.remaining,
94
+ threadsRemaining: threads.remaining,
95
+ contactsRemaining: contacts.remaining
96
+ });
97
+ }
98
+ return result;
99
+ }
100
+ async destroy(timeoutMs = this.flushTimeoutMs) {
101
+ const [messages, threads, contacts] = await Promise.all([
102
+ this.queues.messages.destroy(timeoutMs),
103
+ this.queues.threads.destroy(timeoutMs),
104
+ this.queues.contacts.destroy(timeoutMs)
105
+ ]);
106
+ const result = this.toDrainResult(messages, threads, contacts);
107
+ if (result.remaining > 0) {
108
+ this.logger.warn('write-behind destroy finished with pending writes', {
109
+ messagesRemaining: messages.remaining,
110
+ threadsRemaining: threads.remaining,
111
+ contactsRemaining: contacts.remaining
112
+ });
113
+ }
114
+ return result;
115
+ }
116
+ toDrainResult(messages, threads, contacts) {
117
+ return {
118
+ messages,
119
+ threads,
120
+ contacts,
121
+ flushed: messages.flushed + threads.flushed + contacts.flushed,
122
+ remaining: messages.remaining + threads.remaining + contacts.remaining
123
+ };
124
+ }
125
+ }
@@ -0,0 +1,46 @@
1
+ import { hmacSign, importHmacKey } from '../../crypto/core/index.js';
2
+ import { TEXT_ENCODER } from '../../util/bytes.js';
3
+ import { setBoundedMapEntry } from '../../util/collections.js';
4
+ const CS_TOKEN_CACHE_MAX = 5;
5
+ export class CsTokenGenerator {
6
+ constructor() {
7
+ this.cachedKey = null;
8
+ this.cachedSalt = null;
9
+ this.cache = new Map();
10
+ }
11
+ async generate(nctSalt, accountLid) {
12
+ const cached = this.cache.get(accountLid);
13
+ if (cached && this.isSameSalt(nctSalt)) {
14
+ return cached;
15
+ }
16
+ const key = await this.resolveKey(nctSalt);
17
+ const result = await hmacSign(key, TEXT_ENCODER.encode(accountLid));
18
+ setBoundedMapEntry(this.cache, accountLid, result, CS_TOKEN_CACHE_MAX);
19
+ return result;
20
+ }
21
+ invalidate() {
22
+ this.cachedKey = null;
23
+ this.cachedSalt = null;
24
+ this.cache.clear();
25
+ }
26
+ isSameSalt(salt) {
27
+ if (!this.cachedSalt || this.cachedSalt.length !== salt.length) {
28
+ return false;
29
+ }
30
+ for (let i = 0; i < salt.length; i += 1) {
31
+ if (this.cachedSalt[i] !== salt[i]) {
32
+ return false;
33
+ }
34
+ }
35
+ return true;
36
+ }
37
+ async resolveKey(salt) {
38
+ if (this.cachedKey && this.isSameSalt(salt)) {
39
+ return this.cachedKey;
40
+ }
41
+ this.cachedKey = await importHmacKey(salt);
42
+ this.cachedSalt = salt;
43
+ this.cache.clear();
44
+ return this.cachedKey;
45
+ }
46
+ }
@@ -0,0 +1,18 @@
1
+ export function computeBucket(unixTimeS, durationS) {
2
+ return Math.floor(unixTimeS / durationS);
3
+ }
4
+ export function tokenExpirationCutoffS(nowS, durationS, numBuckets) {
5
+ const currentBucket = computeBucket(nowS, durationS);
6
+ const cutoffBucket = currentBucket - numBuckets;
7
+ return cutoffBucket * durationS;
8
+ }
9
+ export function isTokenExpired(tokenTimestampS, nowS, durationS, numBuckets) {
10
+ const cutoff = tokenExpirationCutoffS(nowS, durationS, numBuckets);
11
+ return tokenTimestampS < cutoff;
12
+ }
13
+ export function shouldSendNewToken(senderTimestampS, nowS, senderDurationS) {
14
+ return computeBucket(senderTimestampS, senderDurationS) !== computeBucket(nowS, senderDurationS);
15
+ }
16
+ export function clampDuration(durationS, maxDurationS) {
17
+ return Math.min(durationS, maxDurationS);
18
+ }
@@ -6,5 +6,5 @@ export { X25519 } from '../curves/X25519.js';
6
6
  export { hkdf, hkdfSplit } from '../core/hkdf.js';
7
7
  export { toSerializedPubKey, toRawPubKey, prependVersion, readVersionedContent } from '../core/keys.js';
8
8
  export { buildNonce } from '../core/nonce.js';
9
- export { randomBytesAsync, randomIntAsync } from '../core/random.js';
10
- export { sha1, sha256, sha512, importAesGcmKey, aesGcmEncrypt, aesGcmDecrypt, importAesCbcKey, aesCbcEncrypt, aesCbcDecrypt, importHmacKey, importHmacSha512Key, hmacSign, pbkdf2DeriveAesCtrKey, aesCtrEncrypt, aesCtrDecrypt, ed25519VerifyRaw } from '../core/primitives.js';
9
+ export { randomBytesAsync, randomFillAsync, randomIntAsync } from '../core/random.js';
10
+ export { sha1, sha256, sha512, importAesGcmKey, aesGcmEncrypt, aesGcmDecrypt, importAesCbcKey, aesCbcEncrypt, aesCbcDecrypt, importHmacKey, importHmacSha512Key, hmacSign, pbkdf2DeriveAesCtrKey, aesCtrEncrypt, aesCtrDecrypt } from '../core/primitives.js';
@@ -1,5 +1,5 @@
1
- import { SERIALIZED_PUB_KEY_PREFIX } from '../core/constants.js';
2
1
  import { assertByteLength } from '../../util/bytes.js';
2
+ const SERIALIZED_PUB_KEY_PREFIX = 5;
3
3
  /**
4
4
  * Converts a 32-byte raw public key to 33-byte serialized format (with 0x05 prefix)
5
5
  */
@@ -1,5 +1,7 @@
1
1
  /**
2
2
  * Builds a 12-byte nonce for AES-GCM encryption with counter in the last 4 bytes.
3
+ * Allocates a new buffer per call because concurrent Noise encrypt/decrypt operations
4
+ * may hold references to different nonces simultaneously.
3
5
  * Throws if counter exceeds uint32 range to prevent nonce reuse.
4
6
  */
5
7
  export function buildNonce(counter) {
@@ -90,10 +90,3 @@ export async function aesCtrEncrypt(key, counter, plaintext) {
90
90
  export async function aesCtrDecrypt(key, counter, ciphertext) {
91
91
  return toBytesView(await webcrypto.subtle.decrypt({ name: 'AES-CTR', counter, length: 64 }, key, ciphertext));
92
92
  }
93
- // ============================================
94
- // Ed25519 raw verify (for Signal variant sigs)
95
- // ============================================
96
- export async function ed25519VerifyRaw(publicKey, signature, message) {
97
- const cryptoKey = await webcrypto.subtle.importKey('raw', publicKey, { name: 'Ed25519' }, false, ['verify']);
98
- return webcrypto.subtle.verify('Ed25519', cryptoKey, signature, message);
99
- }
@@ -1,4 +1,4 @@
1
- import { randomBytes, randomInt } from 'node:crypto';
1
+ import { randomBytes, randomFill, randomInt } from 'node:crypto';
2
2
  import { promisify } from 'node:util';
3
3
  import { toBytesView } from '../../util/bytes.js';
4
4
  const randomBytesAsyncImpl = promisify(randomBytes);
@@ -6,4 +6,25 @@ const randomIntAsyncImpl = promisify(randomInt);
6
6
  export async function randomBytesAsync(size) {
7
7
  return toBytesView(await randomBytesAsyncImpl(size));
8
8
  }
9
+ export async function randomFillAsync(target, offset, size) {
10
+ await new Promise((resolve, reject) => {
11
+ const onDone = (error) => {
12
+ if (error) {
13
+ reject(error);
14
+ return;
15
+ }
16
+ resolve();
17
+ };
18
+ if (offset === undefined) {
19
+ randomFill(target, onDone);
20
+ return;
21
+ }
22
+ if (size === undefined) {
23
+ randomFill(target, offset, onDone);
24
+ return;
25
+ }
26
+ randomFill(target, offset, size, onDone);
27
+ });
28
+ return target;
29
+ }
9
30
  export const randomIntAsync = randomIntAsyncImpl;
@@ -1,9 +1,24 @@
1
1
  import { webcrypto } from 'node:crypto';
2
2
  import { X25519_PKCS8_PREFIX } from '../curves/constants.js';
3
3
  import { pkcs8FromRawPrivate } from '../curves/types.js';
4
- import { bigIntToBytesLE, bytesToBigIntLE } from '../math/le.js';
5
- import { FIELD_P, mod, modInv } from '../math/mod.js';
4
+ import { FE_ONE } from '../math/constants.js';
5
+ import { fe, feAdd, feFromBytes, feInv, feMul, fePack, feSub } from '../math/fe.js';
6
6
  import { assertByteLength, decodeBase64Url, toBytesView } from '../../util/bytes.js';
7
+ // Pre-allocated temps for montgomeryToEdwardsPublic (safe: single-threaded)
8
+ const _mx = fe();
9
+ const _m1 = fe();
10
+ const _m2 = fe();
11
+ const _m3 = fe();
12
+ // p-1 = 2^255-20 in LE bytes: 0xEC, 0xFF×30, 0x7F
13
+ // Mask bit 255 before comparing (non-canonical inputs may have it set)
14
+ function isFieldPMinus1(b) {
15
+ if (b[0] !== 0xec || (b[31] & 0x7f) !== 0x7f)
16
+ return false;
17
+ for (let i = 1; i < 31; i++)
18
+ if (b[i] !== 0xff)
19
+ return false;
20
+ return true;
21
+ }
7
22
  export function clampCurvePrivateKeyInPlace(privateKey) {
8
23
  assertByteLength(privateKey, 32, `invalid curve25519 private key length ${privateKey.length}`);
9
24
  privateKey[0] &= 248;
@@ -13,12 +28,16 @@ export function clampCurvePrivateKeyInPlace(privateKey) {
13
28
  }
14
29
  export function montgomeryToEdwardsPublic(curvePublicKey, signBit) {
15
30
  assertByteLength(curvePublicKey, 32, `invalid curve25519 public key length ${curvePublicKey.length}`);
16
- const x = bytesToBigIntLE(curvePublicKey);
17
- if (x === FIELD_P - 1n) {
31
+ if (isFieldPMinus1(curvePublicKey)) {
18
32
  throw new Error('invalid curve25519 low-order public key');
19
33
  }
20
- const y = mod((x - 1n) * modInv(x + 1n));
21
- const encoded = bigIntToBytesLE(y, 32);
34
+ feFromBytes(_mx, curvePublicKey);
35
+ feSub(_m1, _mx, FE_ONE);
36
+ feAdd(_m2, _mx, FE_ONE);
37
+ feInv(_m3, _m2);
38
+ feMul(_m1, _m1, _m3);
39
+ const encoded = new Uint8Array(32);
40
+ fePack(encoded, _m1);
22
41
  encoded[31] = (encoded[31] & 0x7f) | (signBit & 0x80);
23
42
  return encoded;
24
43
  }
@@ -1 +1,2 @@
1
1
  export * from './core/index.js';
2
+ export { X25519 } from './curves/X25519.js';
@@ -1,41 +1,18 @@
1
+ import { fe, feFromBigInt } from '../math/fe.js';
1
2
  export const FIELD_P = (1n << 255n) - 19n;
2
3
  export const GROUP_L = (1n << 252n) + 27742317777372353535851937790883648493n;
3
- function modField(value) {
4
- const remainder = value % FIELD_P;
5
- return remainder >= 0n ? remainder : remainder + FIELD_P;
6
- }
7
- function modPowField(base, exponent) {
8
- let result = 1n;
9
- let current = modField(base);
10
- let power = exponent;
11
- while (power > 0n) {
12
- if ((power & 1n) === 1n) {
13
- result = modField(result * current);
14
- }
15
- current = modField(current * current);
16
- power >>= 1n;
17
- }
18
- return result;
19
- }
20
- function modInvField(value) {
21
- if (value === 0n) {
22
- throw new Error('field inversion by zero');
23
- }
24
- return modPowField(value, FIELD_P - 2n);
25
- }
26
- const BASE_X = 15112221349535400772501151409588531511454012693041857206046113283949847762202n;
27
- const BASE_Y = 46316835694926478169428394003475163141307993866256225615783033603165251855960n;
28
- export const EDWARDS_D = modField(-121665n * modInvField(121666n));
29
- export const TWO_D = modField(2n * EDWARDS_D);
4
+ export const FE_TWO_D = feFromBigInt(16295367250680780974490674513165176452449235426866156013048779062215315747161n);
5
+ export const FE_ZERO = fe();
6
+ export const FE_ONE = feFromBigInt(1n);
30
7
  export const BASE_POINT = Object.freeze({
31
- x: BASE_X,
32
- y: BASE_Y,
33
- z: 1n,
34
- t: modField(BASE_X * BASE_Y)
8
+ x: feFromBigInt(15112221349535400772501151409588531511454012693041857206046113283949847762202n),
9
+ y: feFromBigInt(46316835694926478169428394003475163141307993866256225615783033603165251855960n),
10
+ z: feFromBigInt(1n),
11
+ t: feFromBigInt(46827403850823179245072216630277197565144205554125654976674165829533817101731n)
35
12
  });
36
13
  export const IDENTITY_POINT = Object.freeze({
37
- x: 0n,
38
- y: 1n,
39
- z: 1n,
40
- t: 0n
14
+ x: feFromBigInt(0n),
15
+ y: feFromBigInt(1n),
16
+ z: feFromBigInt(1n),
17
+ t: feFromBigInt(0n)
41
18
  });