wowok 2.2.3 → 2.2.4

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 (297) hide show
  1. package/dist/cjs/bcs/bcs.d.ts +30 -68
  2. package/dist/cjs/bcs/bcs.js +1 -1
  3. package/dist/cjs/bcs/index.js +1 -1
  4. package/dist/cjs/cryptography/index.d.ts +1 -1
  5. package/dist/cjs/cryptography/index.js +1 -1
  6. package/dist/cjs/cryptography/intent.js +1 -1
  7. package/dist/cjs/cryptography/keypair.d.ts +2 -2
  8. package/dist/cjs/cryptography/keypair.js +1 -1
  9. package/dist/cjs/cryptography/publickey.d.ts +1 -1
  10. package/dist/cjs/cryptography/publickey.js +1 -1
  11. package/dist/cjs/cryptography/signature-scheme.d.ts +4 -15
  12. package/dist/cjs/cryptography/signature-scheme.js +1 -1
  13. package/dist/cjs/cryptography/signature.d.ts +1 -9
  14. package/dist/cjs/cryptography/signature.js +1 -1
  15. package/dist/cjs/grpc/client.d.ts +0 -2
  16. package/dist/cjs/grpc/client.js +1 -1
  17. package/dist/cjs/grpc/proto/google/protobuf/any.d.ts +7 -0
  18. package/dist/cjs/grpc/proto/google/protobuf/any.js +1 -1
  19. package/dist/cjs/grpc/proto/google/protobuf/duration.d.ts +8 -0
  20. package/dist/cjs/grpc/proto/google/protobuf/duration.js +1 -1
  21. package/dist/cjs/grpc/proto/google/protobuf/empty.d.ts +8 -0
  22. package/dist/cjs/grpc/proto/google/protobuf/empty.js +1 -1
  23. package/dist/cjs/grpc/proto/google/protobuf/field_mask.d.ts +8 -0
  24. package/dist/cjs/grpc/proto/google/protobuf/field_mask.js +1 -1
  25. package/dist/cjs/grpc/proto/google/protobuf/struct.d.ts +15 -0
  26. package/dist/cjs/grpc/proto/google/protobuf/struct.js +1 -1
  27. package/dist/cjs/grpc/proto/google/protobuf/timestamp.d.ts +8 -0
  28. package/dist/cjs/grpc/proto/google/protobuf/timestamp.js +1 -1
  29. package/dist/cjs/grpc/proto/google/rpc/error_details.d.ts +48 -0
  30. package/dist/cjs/grpc/proto/google/rpc/error_details.js +1 -1
  31. package/dist/cjs/grpc/proto/google/rpc/status.d.ts +8 -0
  32. package/dist/cjs/grpc/proto/google/rpc/status.js +1 -1
  33. package/dist/cjs/grpc/proto/sui/rpc/v2/checkpoint.js +1 -1
  34. package/dist/cjs/grpc/proto/sui/rpc/v2/checkpoint_contents.js +1 -1
  35. package/dist/cjs/grpc/proto/sui/rpc/v2/checkpoint_summary.js +1 -1
  36. package/dist/cjs/grpc/proto/sui/rpc/v2/effects.js +1 -1
  37. package/dist/cjs/grpc/proto/sui/rpc/v2/event.js +1 -1
  38. package/dist/cjs/grpc/proto/sui/rpc/v2/executed_transaction.js +1 -1
  39. package/dist/cjs/grpc/proto/sui/rpc/v2/execution_status.d.ts +2 -2
  40. package/dist/cjs/grpc/proto/sui/rpc/v2/execution_status.js +1 -1
  41. package/dist/cjs/grpc/proto/sui/rpc/v2/ledger_service.js +1 -1
  42. package/dist/cjs/grpc/proto/sui/rpc/v2/move_package.js +1 -1
  43. package/dist/cjs/grpc/proto/sui/rpc/v2/move_package_service.js +1 -1
  44. package/dist/cjs/grpc/proto/sui/rpc/v2/object.js +1 -1
  45. package/dist/cjs/grpc/proto/sui/rpc/v2/signature.d.ts +9 -87
  46. package/dist/cjs/grpc/proto/sui/rpc/v2/signature.js +1 -1
  47. package/dist/cjs/grpc/proto/sui/rpc/v2/signature_scheme.d.ts +2 -6
  48. package/dist/cjs/grpc/proto/sui/rpc/v2/signature_scheme.js +1 -1
  49. package/dist/cjs/grpc/proto/sui/rpc/v2/signature_verification_service.d.ts +0 -2
  50. package/dist/cjs/grpc/proto/sui/rpc/v2/signature_verification_service.js +1 -1
  51. package/dist/cjs/grpc/proto/sui/rpc/v2/state_service.js +1 -1
  52. package/dist/cjs/grpc/proto/sui/rpc/v2/system_state.d.ts +2 -2
  53. package/dist/cjs/grpc/proto/sui/rpc/v2/system_state.js +1 -1
  54. package/dist/cjs/grpc/proto/sui/rpc/v2/transaction.d.ts +13 -51
  55. package/dist/cjs/grpc/proto/sui/rpc/v2/transaction.js +1 -1
  56. package/dist/cjs/grpc/proto/sui/rpc/v2/transaction_execution_service.js +1 -1
  57. package/dist/cjs/index.d.ts +1 -1
  58. package/dist/cjs/index.js +1 -1
  59. package/dist/cjs/jsonRpc/types/chain.d.ts +0 -5
  60. package/dist/cjs/jsonRpc/types/generated.d.ts +5 -57
  61. package/dist/cjs/jsonRpc/types/params.d.ts +0 -17
  62. package/dist/cjs/keypairs/falcon512/index.d.ts +2 -0
  63. package/dist/cjs/keypairs/falcon512/index.js +1 -0
  64. package/dist/cjs/keypairs/falcon512/keypair.d.ts +19 -0
  65. package/dist/cjs/keypairs/falcon512/keypair.js +1 -0
  66. package/dist/{esm/keypairs/ed25519 → cjs/keypairs/falcon512}/publickey.d.ts +2 -2
  67. package/dist/cjs/keypairs/falcon512/publickey.js +1 -0
  68. package/dist/cjs/keypairs/index.d.ts +1 -4
  69. package/dist/cjs/keypairs/index.js +1 -1
  70. package/dist/cjs/utils/move-registry.js +1 -1
  71. package/dist/cjs/utils/sui-types.js +1 -1
  72. package/dist/cjs/verify/verify.js +1 -1
  73. package/dist/cjs/w/call/arbitration.js +1 -1
  74. package/dist/cjs/w/call/base.js +1 -1
  75. package/dist/cjs/w/call/contact.js +1 -1
  76. package/dist/cjs/w/call/demand.js +1 -1
  77. package/dist/cjs/w/call/guard.js +1 -1
  78. package/dist/cjs/w/call/machine.js +1 -1
  79. package/dist/cjs/w/call/personal.js +1 -1
  80. package/dist/cjs/w/call/proof.d.ts +3 -3
  81. package/dist/cjs/w/call/proof.js +1 -1
  82. package/dist/cjs/w/call/repository.js +1 -1
  83. package/dist/cjs/w/call/reward.js +1 -1
  84. package/dist/cjs/w/call/service.js +1 -1
  85. package/dist/cjs/w/call/treasury.js +1 -1
  86. package/dist/cjs/w/local/account.d.ts +11 -4
  87. package/dist/cjs/w/local/account.js +1 -1
  88. package/dist/cjs/w/local/storage.js +1 -1
  89. package/dist/cjs/w/local/util.js +1 -1
  90. package/dist/cjs/w/local/wip.d.ts +1 -1
  91. package/dist/cjs/w/local/wip.js +1 -1
  92. package/dist/cjs/w/messenger/crypto.d.ts +1 -3
  93. package/dist/cjs/w/messenger/crypto.js +1 -1
  94. package/dist/cjs/w/messenger/messenger-api.js +1 -1
  95. package/dist/cjs/w/messenger/messenger-manager.js +1 -1
  96. package/dist/cjs/w/messenger/messenger.js +1 -1
  97. package/dist/cjs/w/messenger/pq/crypto.d.ts +6 -6
  98. package/dist/cjs/w/messenger/pq/crypto.js +1 -1
  99. package/dist/cjs/w/messenger/pq/pqxdh.d.ts +3 -6
  100. package/dist/cjs/w/messenger/pq/pqxdh.js +1 -1
  101. package/dist/cjs/w/messenger/pq/session.d.ts +6 -4
  102. package/dist/cjs/w/messenger/pq/session.js +1 -1
  103. package/dist/cjs/w/messenger/pq/spqr.js +1 -1
  104. package/dist/cjs/w/messenger/pq/store-adapter.d.ts +1 -3
  105. package/dist/cjs/w/messenger/pq/store-adapter.js +1 -1
  106. package/dist/cjs/w/messenger/pq/types.d.ts +4 -5
  107. package/dist/cjs/w/messenger/pq/types.js +1 -1
  108. package/dist/cjs/w/messenger/session.d.ts +4 -5
  109. package/dist/cjs/w/messenger/session.js +1 -1
  110. package/dist/cjs/w/messenger/storage.js +1 -1
  111. package/dist/cjs/w/messenger/types.d.ts +7 -10
  112. package/dist/cjs/w/messenger/types.js +1 -1
  113. package/dist/cjs/w/query/object.js +1 -1
  114. package/dist/esm/bcs/bcs.d.ts +30 -68
  115. package/dist/esm/bcs/bcs.js +1 -1
  116. package/dist/esm/bcs/index.js +1 -1
  117. package/dist/esm/cryptography/index.d.ts +1 -1
  118. package/dist/esm/cryptography/index.js +1 -1
  119. package/dist/esm/cryptography/intent.js +1 -1
  120. package/dist/esm/cryptography/keypair.d.ts +2 -2
  121. package/dist/esm/cryptography/keypair.js +1 -1
  122. package/dist/esm/cryptography/publickey.d.ts +1 -1
  123. package/dist/esm/cryptography/publickey.js +1 -1
  124. package/dist/esm/cryptography/signature-scheme.d.ts +4 -15
  125. package/dist/esm/cryptography/signature-scheme.js +1 -1
  126. package/dist/esm/cryptography/signature.d.ts +1 -9
  127. package/dist/esm/cryptography/signature.js +1 -1
  128. package/dist/esm/grpc/client.d.ts +0 -2
  129. package/dist/esm/grpc/client.js +1 -1
  130. package/dist/esm/grpc/proto/google/protobuf/any.d.ts +7 -0
  131. package/dist/esm/grpc/proto/google/protobuf/any.js +1 -1
  132. package/dist/esm/grpc/proto/google/protobuf/duration.d.ts +8 -0
  133. package/dist/esm/grpc/proto/google/protobuf/duration.js +1 -1
  134. package/dist/esm/grpc/proto/google/protobuf/empty.d.ts +8 -0
  135. package/dist/esm/grpc/proto/google/protobuf/empty.js +1 -1
  136. package/dist/esm/grpc/proto/google/protobuf/field_mask.d.ts +8 -0
  137. package/dist/esm/grpc/proto/google/protobuf/field_mask.js +1 -1
  138. package/dist/esm/grpc/proto/google/protobuf/struct.d.ts +15 -0
  139. package/dist/esm/grpc/proto/google/protobuf/struct.js +1 -1
  140. package/dist/esm/grpc/proto/google/protobuf/timestamp.d.ts +8 -0
  141. package/dist/esm/grpc/proto/google/protobuf/timestamp.js +1 -1
  142. package/dist/esm/grpc/proto/google/rpc/error_details.d.ts +48 -0
  143. package/dist/esm/grpc/proto/google/rpc/error_details.js +1 -1
  144. package/dist/esm/grpc/proto/google/rpc/status.d.ts +8 -0
  145. package/dist/esm/grpc/proto/google/rpc/status.js +1 -1
  146. package/dist/esm/grpc/proto/sui/rpc/v2/checkpoint.js +1 -1
  147. package/dist/esm/grpc/proto/sui/rpc/v2/checkpoint_contents.js +1 -1
  148. package/dist/esm/grpc/proto/sui/rpc/v2/checkpoint_summary.js +1 -1
  149. package/dist/esm/grpc/proto/sui/rpc/v2/effects.js +1 -1
  150. package/dist/esm/grpc/proto/sui/rpc/v2/event.js +1 -1
  151. package/dist/esm/grpc/proto/sui/rpc/v2/executed_transaction.js +1 -1
  152. package/dist/esm/grpc/proto/sui/rpc/v2/execution_status.d.ts +2 -2
  153. package/dist/esm/grpc/proto/sui/rpc/v2/execution_status.js +1 -1
  154. package/dist/esm/grpc/proto/sui/rpc/v2/ledger_service.js +1 -1
  155. package/dist/esm/grpc/proto/sui/rpc/v2/move_package.js +1 -1
  156. package/dist/esm/grpc/proto/sui/rpc/v2/move_package_service.js +1 -1
  157. package/dist/esm/grpc/proto/sui/rpc/v2/object.js +1 -1
  158. package/dist/esm/grpc/proto/sui/rpc/v2/signature.d.ts +9 -87
  159. package/dist/esm/grpc/proto/sui/rpc/v2/signature.js +1 -1
  160. package/dist/esm/grpc/proto/sui/rpc/v2/signature_scheme.d.ts +2 -6
  161. package/dist/esm/grpc/proto/sui/rpc/v2/signature_scheme.js +1 -1
  162. package/dist/esm/grpc/proto/sui/rpc/v2/signature_verification_service.d.ts +0 -2
  163. package/dist/esm/grpc/proto/sui/rpc/v2/signature_verification_service.js +1 -1
  164. package/dist/esm/grpc/proto/sui/rpc/v2/state_service.js +1 -1
  165. package/dist/esm/grpc/proto/sui/rpc/v2/system_state.d.ts +2 -2
  166. package/dist/esm/grpc/proto/sui/rpc/v2/system_state.js +1 -1
  167. package/dist/esm/grpc/proto/sui/rpc/v2/transaction.d.ts +13 -51
  168. package/dist/esm/grpc/proto/sui/rpc/v2/transaction.js +1 -1
  169. package/dist/esm/grpc/proto/sui/rpc/v2/transaction_execution_service.js +1 -1
  170. package/dist/esm/index.d.ts +1 -1
  171. package/dist/esm/index.js +1 -1
  172. package/dist/esm/jsonRpc/types/chain.d.ts +0 -5
  173. package/dist/esm/jsonRpc/types/generated.d.ts +5 -57
  174. package/dist/esm/jsonRpc/types/params.d.ts +0 -17
  175. package/dist/esm/keypairs/falcon512/index.d.ts +2 -0
  176. package/dist/esm/keypairs/falcon512/index.js +1 -0
  177. package/dist/esm/keypairs/falcon512/keypair.d.ts +19 -0
  178. package/dist/esm/keypairs/falcon512/keypair.js +1 -0
  179. package/dist/{cjs/keypairs/ed25519 → esm/keypairs/falcon512}/publickey.d.ts +2 -2
  180. package/dist/esm/keypairs/falcon512/publickey.js +1 -0
  181. package/dist/esm/keypairs/index.d.ts +1 -4
  182. package/dist/esm/keypairs/index.js +1 -1
  183. package/dist/esm/utils/move-registry.js +1 -1
  184. package/dist/esm/utils/sui-types.js +1 -1
  185. package/dist/esm/verify/verify.js +1 -1
  186. package/dist/esm/w/call/arbitration.js +1 -1
  187. package/dist/esm/w/call/base.js +1 -1
  188. package/dist/esm/w/call/contact.js +1 -1
  189. package/dist/esm/w/call/demand.js +1 -1
  190. package/dist/esm/w/call/guard.js +1 -1
  191. package/dist/esm/w/call/machine.js +1 -1
  192. package/dist/esm/w/call/personal.js +1 -1
  193. package/dist/esm/w/call/proof.d.ts +3 -3
  194. package/dist/esm/w/call/proof.js +1 -1
  195. package/dist/esm/w/call/repository.js +1 -1
  196. package/dist/esm/w/call/reward.js +1 -1
  197. package/dist/esm/w/call/service.js +1 -1
  198. package/dist/esm/w/call/treasury.js +1 -1
  199. package/dist/esm/w/local/account.d.ts +11 -4
  200. package/dist/esm/w/local/account.js +1 -1
  201. package/dist/esm/w/local/storage.js +1 -1
  202. package/dist/esm/w/local/util.js +1 -1
  203. package/dist/esm/w/local/wip.d.ts +1 -1
  204. package/dist/esm/w/local/wip.js +1 -1
  205. package/dist/esm/w/messenger/crypto.d.ts +1 -3
  206. package/dist/esm/w/messenger/crypto.js +1 -1
  207. package/dist/esm/w/messenger/messenger-api.js +1 -1
  208. package/dist/esm/w/messenger/messenger-manager.js +1 -1
  209. package/dist/esm/w/messenger/messenger.js +1 -1
  210. package/dist/esm/w/messenger/pq/crypto.d.ts +6 -6
  211. package/dist/esm/w/messenger/pq/crypto.js +1 -1
  212. package/dist/esm/w/messenger/pq/pqxdh.d.ts +3 -6
  213. package/dist/esm/w/messenger/pq/pqxdh.js +1 -1
  214. package/dist/esm/w/messenger/pq/session.d.ts +6 -4
  215. package/dist/esm/w/messenger/pq/session.js +1 -1
  216. package/dist/esm/w/messenger/pq/spqr.js +1 -1
  217. package/dist/esm/w/messenger/pq/store-adapter.d.ts +1 -3
  218. package/dist/esm/w/messenger/pq/store-adapter.js +1 -1
  219. package/dist/esm/w/messenger/pq/types.d.ts +4 -5
  220. package/dist/esm/w/messenger/pq/types.js +1 -1
  221. package/dist/esm/w/messenger/session.d.ts +4 -5
  222. package/dist/esm/w/messenger/session.js +1 -1
  223. package/dist/esm/w/messenger/storage.js +1 -1
  224. package/dist/esm/w/messenger/types.d.ts +7 -10
  225. package/dist/esm/w/messenger/types.js +1 -1
  226. package/dist/esm/w/query/object.js +1 -1
  227. package/package.json +24 -24
  228. package/dist/cjs/grpc/proto/sui/rpc/v2/jwk.d.ts +0 -20
  229. package/dist/cjs/grpc/proto/sui/rpc/v2/jwk.js +0 -1
  230. package/dist/cjs/grpc/proto/sui/rpc/v2/name_service.client.d.ts +0 -23
  231. package/dist/cjs/grpc/proto/sui/rpc/v2/name_service.client.js +0 -1
  232. package/dist/cjs/grpc/proto/sui/rpc/v2/name_service.d.ts +0 -47
  233. package/dist/cjs/grpc/proto/sui/rpc/v2/name_service.js +0 -1
  234. package/dist/cjs/keypairs/ed25519/ed25519-hd-key.d.ts +0 -8
  235. package/dist/cjs/keypairs/ed25519/ed25519-hd-key.js +0 -1
  236. package/dist/cjs/keypairs/ed25519/index.d.ts +0 -2
  237. package/dist/cjs/keypairs/ed25519/index.js +0 -1
  238. package/dist/cjs/keypairs/ed25519/keypair.d.ts +0 -22
  239. package/dist/cjs/keypairs/ed25519/keypair.js +0 -1
  240. package/dist/cjs/keypairs/ed25519/publickey.js +0 -1
  241. package/dist/cjs/keypairs/passkey/index.d.ts +0 -3
  242. package/dist/cjs/keypairs/passkey/index.js +0 -1
  243. package/dist/cjs/keypairs/passkey/keypair.d.ts +0 -33
  244. package/dist/cjs/keypairs/passkey/keypair.js +0 -1
  245. package/dist/cjs/keypairs/passkey/publickey.d.ts +0 -25
  246. package/dist/cjs/keypairs/passkey/publickey.js +0 -1
  247. package/dist/cjs/keypairs/passkey/types.d.ts +0 -6
  248. package/dist/cjs/keypairs/passkey/types.js +0 -1
  249. package/dist/cjs/keypairs/secp256k1/index.d.ts +0 -2
  250. package/dist/cjs/keypairs/secp256k1/index.js +0 -1
  251. package/dist/cjs/keypairs/secp256k1/keypair.d.ts +0 -22
  252. package/dist/cjs/keypairs/secp256k1/keypair.js +0 -1
  253. package/dist/cjs/keypairs/secp256k1/publickey.d.ts +0 -11
  254. package/dist/cjs/keypairs/secp256k1/publickey.js +0 -1
  255. package/dist/cjs/keypairs/secp256r1/index.d.ts +0 -2
  256. package/dist/cjs/keypairs/secp256r1/index.js +0 -1
  257. package/dist/cjs/keypairs/secp256r1/keypair.d.ts +0 -22
  258. package/dist/cjs/keypairs/secp256r1/keypair.js +0 -1
  259. package/dist/cjs/keypairs/secp256r1/publickey.d.ts +0 -11
  260. package/dist/cjs/keypairs/secp256r1/publickey.js +0 -1
  261. package/dist/cjs/utils/suins.d.ts +0 -2
  262. package/dist/cjs/utils/suins.js +0 -1
  263. package/dist/esm/grpc/proto/sui/rpc/v2/jwk.d.ts +0 -20
  264. package/dist/esm/grpc/proto/sui/rpc/v2/jwk.js +0 -1
  265. package/dist/esm/grpc/proto/sui/rpc/v2/name_service.client.d.ts +0 -23
  266. package/dist/esm/grpc/proto/sui/rpc/v2/name_service.client.js +0 -1
  267. package/dist/esm/grpc/proto/sui/rpc/v2/name_service.d.ts +0 -47
  268. package/dist/esm/grpc/proto/sui/rpc/v2/name_service.js +0 -1
  269. package/dist/esm/keypairs/ed25519/ed25519-hd-key.d.ts +0 -8
  270. package/dist/esm/keypairs/ed25519/ed25519-hd-key.js +0 -1
  271. package/dist/esm/keypairs/ed25519/index.d.ts +0 -2
  272. package/dist/esm/keypairs/ed25519/index.js +0 -1
  273. package/dist/esm/keypairs/ed25519/keypair.d.ts +0 -22
  274. package/dist/esm/keypairs/ed25519/keypair.js +0 -1
  275. package/dist/esm/keypairs/ed25519/publickey.js +0 -1
  276. package/dist/esm/keypairs/passkey/index.d.ts +0 -3
  277. package/dist/esm/keypairs/passkey/index.js +0 -1
  278. package/dist/esm/keypairs/passkey/keypair.d.ts +0 -33
  279. package/dist/esm/keypairs/passkey/keypair.js +0 -1
  280. package/dist/esm/keypairs/passkey/publickey.d.ts +0 -25
  281. package/dist/esm/keypairs/passkey/publickey.js +0 -1
  282. package/dist/esm/keypairs/passkey/types.d.ts +0 -6
  283. package/dist/esm/keypairs/passkey/types.js +0 -1
  284. package/dist/esm/keypairs/secp256k1/index.d.ts +0 -2
  285. package/dist/esm/keypairs/secp256k1/index.js +0 -1
  286. package/dist/esm/keypairs/secp256k1/keypair.d.ts +0 -22
  287. package/dist/esm/keypairs/secp256k1/keypair.js +0 -1
  288. package/dist/esm/keypairs/secp256k1/publickey.d.ts +0 -11
  289. package/dist/esm/keypairs/secp256k1/publickey.js +0 -1
  290. package/dist/esm/keypairs/secp256r1/index.d.ts +0 -2
  291. package/dist/esm/keypairs/secp256r1/index.js +0 -1
  292. package/dist/esm/keypairs/secp256r1/keypair.d.ts +0 -22
  293. package/dist/esm/keypairs/secp256r1/keypair.js +0 -1
  294. package/dist/esm/keypairs/secp256r1/publickey.d.ts +0 -11
  295. package/dist/esm/keypairs/secp256r1/publickey.js +0 -1
  296. package/dist/esm/utils/suins.d.ts +0 -2
  297. package/dist/esm/utils/suins.js +0 -1
@@ -1 +1 @@
1
- import{x25519}from'@noble/curves/ed25519';import{ed25519}from'@noble/curves/ed25519';import{sha256}from'@noble/hashes/sha256';import{sha512}from'@noble/hashes/sha512';import{hmac}from'@noble/hashes/hmac';import{hkdf}from'@noble/hashes/hkdf';import{randomBytes}from'@noble/hashes/utils';import{ml_kem768}from'@noble/post-quantum/ml-kem.js';import a184a from'node:crypto';import{ROOT_KEY_SIZE,CHAIN_KEY_SIZE,MESSAGE_KEY_SIZE,DH_KEY_SIZE,AES_GCM_IV_SIZE}from'./types.js';export function generateRandomBytes(a){return randomBytes(a);}export function generateX25519KeyPair(){const a=randomBytes(DH_KEY_SIZE),b=x25519['getPublicKey'](a);return{'publicKey':b,'privateKey':a};}export function x25519DH(a,b){return x25519['getSharedSecret'](a,b);}export function generateEd25519KeyPair(){const a=randomBytes(DH_KEY_SIZE),b=ed25519['getPublicKey'](a);return{'publicKey':b,'privateKey':a};}export function ed25519Sign(a,b){return ed25519['sign'](b,a);}export function ed25519Verify(a,b,c){try{return ed25519['verify'](c,b,a);}catch{return![];}}export function ed25519PrivateKeyToX25519(a){const b=sha512(a),c=new Uint8Array(b['slice'](0x0,0x20));return c[0x0]&=0xf8,c[0x1f]&=0x7f,c[0x1f]|=0x40,c;}export function ed25519PublicKeyToX25519(a){return x25519['getPublicKey'](ed25519PublicKeyToX25519(a));}export function generateMLKEMKeyPair(){const {publicKey:a,secretKey:b}=ml_kem768['keygen']();return{'publicKey':a,'secretKey':b};}export function mlkemEncapsulate(a){const {cipherText:b,sharedSecret:c}=ml_kem768['encapsulate'](a);return{'ciphertext':b,'sharedSecret':c};}export function mlkemDecapsulate(a,b){return ml_kem768['decapsulate'](a,b);}export function hkdfDerive(a,b,c,d){return hkdf(sha256,a,d||new Uint8Array(0x0),b,c);}export function hkdfChainKey(a,b){const c=new Uint8Array(a['length']+b['length']);c['set'](a),c['set'](b,a['length']);const d=hkdfDerive(c,new TextEncoder()['encode']('WowokPQChainKey'),ROOT_KEY_SIZE+CHAIN_KEY_SIZE);return{'rootKey':d['slice'](0x0,ROOT_KEY_SIZE),'chainKey':d['slice'](ROOT_KEY_SIZE,ROOT_KEY_SIZE+CHAIN_KEY_SIZE)};}export function hkdfMessageKey(a){const b=hkdfDerive(a,new TextEncoder()['encode']('WowokPQMessageKey'),MESSAGE_KEY_SIZE+CHAIN_KEY_SIZE);return{'messageKey':b['slice'](0x0,MESSAGE_KEY_SIZE),'nextChainKey':b['slice'](MESSAGE_KEY_SIZE,MESSAGE_KEY_SIZE+CHAIN_KEY_SIZE)};}export function hmacSha256(a,b){return hmac(sha256,a,b);}export function aesGcmEncrypt(a,b,c){const d=randomBytes(AES_GCM_IV_SIZE),e=Buffer['from'](a),f=Buffer['from'](d),g=Buffer['from'](b),h=Buffer['from'](c),i=a184a['createCipheriv']('aes-256-gcm',e,f);i['setAAD'](h);const j=Buffer['concat']([i['update'](g),i['final']()]),k=i['getAuthTag']();return{'ciphertext':new Uint8Array(j),'iv':d,'tag':new Uint8Array(k)};}export function aesGcmDecrypt(a,b,c,d,e){const f=Buffer['from'](a),g=Buffer['from'](c),h=Buffer['from'](b),i=Buffer['from'](d),j=Buffer['from'](e),k=a184a['createDecipheriv']('aes-256-gcm',f,g);k['setAAD'](j),k['setAuthTag'](i);const l=Buffer['concat']([k['update'](h),k['final']()]);return new Uint8Array(l);}export function sha256Hash(a){return sha256(a);}export function constantTimeEqual(c,d){if(c['length']!==d['length'])return![];let e=0x0;for(let f=0x0;f<c['length'];f++){e|=c[f]^d[f];}return e===0x0;}export function bytesToBase64(a){return Buffer['from'](a)['toString']('base64');}export function base64ToBytes(a){return new Uint8Array(Buffer['from'](a,'base64'));}export function bytesToHex(a){return Buffer['from'](a)['toString']('hex');}export function hexToBytes(a){return new Uint8Array(Buffer['from'](a,'hex'));}export function concatBytes(...a){const b=a['reduce']((e,f)=>e+f['length'],0x0),c=new Uint8Array(b);let d=0x0;for(const e of a){c['set'](e,d),d+=e['length'];}return c;}export function deriveRegistrationId(a){const b=(a[0x0]<<0x8|a[0x1])>>>0x0;return b===0x0?0x1:b;}
1
+ import{x25519}from'@noble/curves/ed25519';import{falcon512padded}from'@noble/post-quantum/falcon.js';import{sha256}from'@noble/hashes/sha256';import{hmac}from'@noble/hashes/hmac';import{hkdf}from'@noble/hashes/hkdf';import{randomBytes}from'@noble/hashes/utils';import{ml_kem768}from'@noble/post-quantum/ml-kem.js';import a169a from'node:crypto';import{ROOT_KEY_SIZE,CHAIN_KEY_SIZE,MESSAGE_KEY_SIZE,DH_KEY_SIZE,AES_GCM_IV_SIZE}from'./types.js';export function generateRandomBytes(a){return randomBytes(a);}export function generateX25519KeyPair(){const a=randomBytes(DH_KEY_SIZE),b=x25519['getPublicKey'](a);return{'publicKey':b,'privateKey':a};}export function x25519DH(a,b){return x25519['getSharedSecret'](a,b);}export function generateFalcon512KeyPair(){const {publicKey:a,secretKey:b}=falcon512padded['keygen']();return{'publicKey':a,'privateKey':b};}export function falcon512Sign(a,b){return falcon512padded['sign'](b,a);}export function falcon512Verify(a,b,c){try{return falcon512padded['verify'](c,b,a);}catch{return![];}}export function generateMLKEMKeyPair(){const {publicKey:a,secretKey:b}=ml_kem768['keygen']();return{'publicKey':a,'secretKey':b};}export function mlkemEncapsulate(a){const {cipherText:b,sharedSecret:c}=ml_kem768['encapsulate'](a);return{'ciphertext':b,'sharedSecret':c};}export function mlkemDecapsulate(a,b){return ml_kem768['decapsulate'](a,b);}export function hkdfDerive(a,b,c,d){return hkdf(sha256,a,d||new Uint8Array(0x0),b,c);}export function hkdfChainKey(a,b){const c=new Uint8Array(a['length']+b['length']);c['set'](a),c['set'](b,a['length']);const d=hkdfDerive(c,new TextEncoder()['encode']('WowokPQChainKey'),ROOT_KEY_SIZE+CHAIN_KEY_SIZE);return{'rootKey':d['slice'](0x0,ROOT_KEY_SIZE),'chainKey':d['slice'](ROOT_KEY_SIZE,ROOT_KEY_SIZE+CHAIN_KEY_SIZE)};}export function hkdfMessageKey(a){const b=hkdfDerive(a,new TextEncoder()['encode']('WowokPQMessageKey'),MESSAGE_KEY_SIZE+CHAIN_KEY_SIZE);return{'messageKey':b['slice'](0x0,MESSAGE_KEY_SIZE),'nextChainKey':b['slice'](MESSAGE_KEY_SIZE,MESSAGE_KEY_SIZE+CHAIN_KEY_SIZE)};}export function hmacSha256(a,b){return hmac(sha256,a,b);}export function aesGcmEncrypt(a,b,c){const d=randomBytes(AES_GCM_IV_SIZE),e=Buffer['from'](a),f=Buffer['from'](d),g=Buffer['from'](b),h=Buffer['from'](c),i=a169a['createCipheriv']('aes-256-gcm',e,f);i['setAAD'](h);const j=Buffer['concat']([i['update'](g),i['final']()]),k=i['getAuthTag']();return{'ciphertext':new Uint8Array(j),'iv':d,'tag':new Uint8Array(k)};}export function aesGcmDecrypt(a,b,c,d,e){const f=Buffer['from'](a),g=Buffer['from'](c),h=Buffer['from'](b),i=Buffer['from'](d),j=Buffer['from'](e),k=a169a['createDecipheriv']('aes-256-gcm',f,g);k['setAAD'](j),k['setAuthTag'](i);const l=Buffer['concat']([k['update'](h),k['final']()]);return new Uint8Array(l);}export function sha256Hash(a){return sha256(a);}export function constantTimeEqual(c,d){if(c['length']!==d['length'])return![];let e=0x0;for(let f=0x0;f<c['length'];f++){e|=c[f]^d[f];}return e===0x0;}export function bytesToBase64(a){return Buffer['from'](a)['toString']('base64');}export function base64ToBytes(a){return new Uint8Array(Buffer['from'](a,'base64'));}export function bytesToHex(a){return Buffer['from'](a)['toString']('hex');}export function hexToBytes(a){return new Uint8Array(Buffer['from'](a,'hex'));}export function concatBytes(...a){const b=a['reduce']((e,f)=>e+f['length'],0x0),c=new Uint8Array(b);let d=0x0;for(const e of a){c['set'](e,d),d+=e['length'];}return c;}export function deriveRegistrationId(a){const b=(a[0x0]<<0x8|a[0x1])>>>0x0;return b===0x0?0x1:b;}export function generateX25519BindingSignature(a,b){return falcon512Sign(a,b);}export function verifyX25519BindingSignature(a,b,c){return falcon512Verify(a,b,c);}
@@ -7,14 +7,11 @@ export interface PQXDHInitiateResult {
7
7
  identityKey: Uint8Array;
8
8
  };
9
9
  }
10
- export declare function pqxdhInitiate(ourIdentityKeyPair: X25519KeyPair, ourEd25519KeyPair: {
11
- publicKey: Uint8Array;
12
- privateKey: Uint8Array;
13
- }, peerBundle: PQPreKeyBundle): PQXDHInitiateResult;
10
+ export declare function pqxdhInitiate(ourIdentityKeyPair: X25519KeyPair, peerBundle: PQPreKeyBundle): PQXDHInitiateResult;
14
11
  export declare function pqxdhReceive(ourIdentityKeyPair: X25519KeyPair, ourSignedPreKeyPair: X25519KeyPair, ourOneTimePreKeyPair: X25519KeyPair | null, ourPQPreKeyPair: MLKEMKeyPair, peerEphemeralPublicKey: Uint8Array, peerIdentityKey: Uint8Array, mlkemCiphertext: Uint8Array): PQXDHResult;
15
12
  export interface GeneratedPreKeyBundle {
16
13
  identityKeyPair: X25519KeyPair;
17
- ed25519KeyPair: {
14
+ falcon512KeyPair: {
18
15
  publicKey: Uint8Array;
19
16
  privateKey: Uint8Array;
20
17
  };
@@ -34,7 +31,7 @@ export interface GeneratedPreKeyBundle {
34
31
  signature: Uint8Array;
35
32
  };
36
33
  }
37
- export declare function generatePreKeyBundle(identityKeyPair: X25519KeyPair, ed25519KeyPair: {
34
+ export declare function generatePreKeyBundle(identityKeyPair: X25519KeyPair, falcon512KeyPair: {
38
35
  publicKey: Uint8Array;
39
36
  privateKey: Uint8Array;
40
37
  }, signedPreKeyId: number, pqPreKeyId: number, oneTimePreKeyCount: number): GeneratedPreKeyBundle;
@@ -1 +1 @@
1
- import{generateX25519KeyPair,x25519DH,ed25519Sign,ed25519Verify,generateMLKEMKeyPair,mlkemEncapsulate,mlkemDecapsulate,hkdfDerive,concatBytes,deriveRegistrationId}from'./crypto.js';import{ROOT_KEY_SIZE,CHAIN_KEY_SIZE}from'./types.js';export function pqxdhInitiate(a,b,c){const d=generateX25519KeyPair(),e=x25519DH(d['privateKey'],c['identityKey']),f=x25519DH(a['privateKey'],c['signedPreKey']['publicKey']),g=x25519DH(d['privateKey'],c['signedPreKey']['publicKey']),{ciphertext:h,sharedSecret:i}=mlkemEncapsulate(c['pqPreKey']['publicKey']);let j;if(c['oneTimePreKey']){const n=x25519DH(d['privateKey'],c['oneTimePreKey']['publicKey']);j=concatBytes(e,f,g,n,i);}else j=concatBytes(e,f,g,i);const k=concatBytes(new TextEncoder()['encode']('WowokPQXDH'),a['publicKey'],c['identityKey']),l=hkdfDerive(j,k,ROOT_KEY_SIZE+CHAIN_KEY_SIZE),m={'rootKey':l['slice'](0x0,ROOT_KEY_SIZE),'chainKey':l['slice'](ROOT_KEY_SIZE,ROOT_KEY_SIZE+CHAIN_KEY_SIZE),'ourDHKeyPair':d,'peerDHPublicKey':c['signedPreKey']['publicKey'],'peerIdentityKey':c['identityKey'],'pqSharedSecret':i};return{'result':m,'initialMessage':{'ephemeralPublicKey':d['publicKey'],'mlkemCiphertext':h,'identityKey':a['publicKey']}};}export function pqxdhReceive(a,b,c,d,e,f,g){const h=x25519DH(a['privateKey'],e),i=x25519DH(b['privateKey'],f),j=x25519DH(b['privateKey'],e),k=mlkemDecapsulate(g,d['secretKey']);let l;if(c){const o=x25519DH(c['privateKey'],e);l=concatBytes(h,i,j,o,k);}else l=concatBytes(h,i,j,k);const m=concatBytes(new TextEncoder()['encode']('WowokPQXDH'),f,a['publicKey']),n=hkdfDerive(l,m,ROOT_KEY_SIZE+CHAIN_KEY_SIZE);return{'rootKey':n['slice'](0x0,ROOT_KEY_SIZE),'chainKey':n['slice'](ROOT_KEY_SIZE,ROOT_KEY_SIZE+CHAIN_KEY_SIZE),'ourDHKeyPair':b,'peerDHPublicKey':e,'peerIdentityKey':f,'pqSharedSecret':k};}export function generatePreKeyBundle(a,b,c,d,e){const f=deriveRegistrationId(a['publicKey']),g=generateX25519KeyPair(),h=ed25519Sign(b['privateKey'],g['publicKey']),j=[];for(let m=0x0;m<e;m++){j['push']({'keyId':m+0x1,'keyPair':generateX25519KeyPair()});}const k=generateMLKEMKeyPair(),l=ed25519Sign(b['privateKey'],k['publicKey']);return{'identityKeyPair':a,'ed25519KeyPair':b,'registrationId':f,'signedPreKey':{'keyId':c,'keyPair':g,'signature':h},'oneTimePreKeys':j,'pqPreKey':{'keyId':d,'keyPair':k,'signature':l}};}export function verifyPreKeyBundle(a){if(!a['ed25519PublicKey']||a['ed25519PublicKey']['length']!==0x20)return![];if(!a['signedPreKey'])return![];const b=ed25519Verify(a['ed25519PublicKey'],a['signedPreKey']['publicKey'],a['signedPreKey']['signature']);if(!b)return![];if(!a['pqPreKey'])return![];const c=ed25519Verify(a['ed25519PublicKey'],a['pqPreKey']['publicKey'],a['pqPreKey']['signature']);if(!c)return![];return!![];}
1
+ import{generateX25519KeyPair,x25519DH,falcon512Sign,falcon512Verify,generateMLKEMKeyPair,mlkemEncapsulate,mlkemDecapsulate,hkdfDerive,concatBytes,deriveRegistrationId}from'./crypto.js';import{ROOT_KEY_SIZE,CHAIN_KEY_SIZE}from'./types.js';export function pqxdhInitiate(a,b){const c=generateX25519KeyPair(),d=x25519DH(c['privateKey'],b['identityKey']),e=x25519DH(a['privateKey'],b['signedPreKey']['publicKey']),f=x25519DH(c['privateKey'],b['signedPreKey']['publicKey']),{ciphertext:g,sharedSecret:h}=mlkemEncapsulate(b['pqPreKey']['publicKey']);let i;if(b['oneTimePreKey']){const m=x25519DH(c['privateKey'],b['oneTimePreKey']['publicKey']);i=concatBytes(d,e,f,m,h);}else i=concatBytes(d,e,f,h);const j=concatBytes(new TextEncoder()['encode']('WowokPQXDH'),a['publicKey'],b['identityKey']),k=hkdfDerive(i,j,ROOT_KEY_SIZE+CHAIN_KEY_SIZE),l={'rootKey':k['slice'](0x0,ROOT_KEY_SIZE),'chainKey':k['slice'](ROOT_KEY_SIZE,ROOT_KEY_SIZE+CHAIN_KEY_SIZE),'ourDHKeyPair':c,'peerDHPublicKey':b['signedPreKey']['publicKey'],'peerIdentityKey':b['identityKey'],'pqSharedSecret':h};return{'result':l,'initialMessage':{'ephemeralPublicKey':c['publicKey'],'mlkemCiphertext':g,'identityKey':a['publicKey']}};}export function pqxdhReceive(a,b,c,d,e,f,g){const h=x25519DH(a['privateKey'],e),i=x25519DH(b['privateKey'],f),j=x25519DH(b['privateKey'],e),k=mlkemDecapsulate(g,d['secretKey']);let l;if(c){const o=x25519DH(c['privateKey'],e);l=concatBytes(h,i,j,o,k);}else l=concatBytes(h,i,j,k);const m=concatBytes(new TextEncoder()['encode']('WowokPQXDH'),f,a['publicKey']),n=hkdfDerive(l,m,ROOT_KEY_SIZE+CHAIN_KEY_SIZE);return{'rootKey':n['slice'](0x0,ROOT_KEY_SIZE),'chainKey':n['slice'](ROOT_KEY_SIZE,ROOT_KEY_SIZE+CHAIN_KEY_SIZE),'ourDHKeyPair':b,'peerDHPublicKey':e,'peerIdentityKey':f,'pqSharedSecret':k};}export function generatePreKeyBundle(a,b,c,d,e){const f=deriveRegistrationId(a['publicKey']),g=generateX25519KeyPair(),h=falcon512Sign(b['privateKey'],g['publicKey']),j=[];for(let m=0x0;m<e;m++){j['push']({'keyId':m+0x1,'keyPair':generateX25519KeyPair()});}const k=generateMLKEMKeyPair(),l=falcon512Sign(b['privateKey'],k['publicKey']);return{'identityKeyPair':a,'falcon512KeyPair':b,'registrationId':f,'signedPreKey':{'keyId':c,'keyPair':g,'signature':h},'oneTimePreKeys':j,'pqPreKey':{'keyId':d,'keyPair':k,'signature':l}};}export function verifyPreKeyBundle(a){if(!a['falcon512PublicKey']||a['falcon512PublicKey']['length']!==0x381)return![];if(!a['signedPreKey'])return![];const b=falcon512Verify(a['falcon512PublicKey'],a['signedPreKey']['publicKey'],a['signedPreKey']['signature']);if(!b)return![];if(!a['pqPreKey'])return![];const c=falcon512Verify(a['falcon512PublicKey'],a['pqPreKey']['publicKey'],a['pqPreKey']['signature']);if(!c)return![];return!![];}
@@ -1,9 +1,7 @@
1
- import type { X25519KeyPair, Ed25519KeyPair, MLKEMKeyPair, PQPreKeyBundle, PQIdentity, EncryptedMessage, SerializedPQSessionState } from "./types.js";
1
+ import type { X25519KeyPair, MLKEMKeyPair, PQPreKeyBundle, PQIdentity, EncryptedMessage, SerializedPQSessionState } from "./types.js";
2
2
  export interface PQSessionStore {
3
3
  getIdentityKeyPair(): Promise<X25519KeyPair | null>;
4
4
  setIdentityKeyPair(keyPair: X25519KeyPair): Promise<void>;
5
- getEd25519KeyPair(): Promise<Ed25519KeyPair | null>;
6
- setEd25519KeyPair(keyPair: Ed25519KeyPair): Promise<void>;
7
5
  getRegistrationId(): Promise<number | null>;
8
6
  setRegistrationId(id: number): Promise<void>;
9
7
  getSignedPreKey(keyId: number): Promise<X25519KeyPair | null>;
@@ -26,7 +24,11 @@ export interface PQSessionStore {
26
24
  export declare class PQSessionCipher {
27
25
  private store;
28
26
  private identity;
29
- constructor(store: PQSessionStore);
27
+ private getFalcon512KeyPair;
28
+ constructor(store: PQSessionStore, getFalcon512KeyPair?: () => Promise<{
29
+ publicKey: Uint8Array;
30
+ privateKey: Uint8Array;
31
+ }>);
30
32
  ensureIdentity(): Promise<PQIdentity>;
31
33
  generatePreKeyBundle(signedPreKeyId: number, pqPreKeyId: number, oneTimePreKeyCount: number): Promise<import("./pqxdh.js").GeneratedPreKeyBundle>;
32
34
  processPreKeyBundle(peerAddress: string, peerDeviceId: number, bundle: PQPreKeyBundle): Promise<void>;
@@ -1 +1 @@
1
- import{generateX25519KeyPair,generateEd25519KeyPair,concatBytes,deriveRegistrationId,bytesToBase64,base64ToBytes}from'./crypto.js';import{pqxdhInitiate,pqxdhReceive,generatePreKeyBundle,verifyPreKeyBundle}from'./pqxdh.js';import{initRatchet,ratchetEncrypt,ratchetDecrypt,serializeRatchetState,deserializeRatchetState}from'./ratchet.js';import{initSPQR,spqrGetNextChunk,spqrReceiveChunk,spqrOnPeerPQPKReceived,serializeSPQRState,deserializeSPQRState}from'./spqr.js';import{packChunk,SHARD_SIZE}from'./erasure.js';import{MessageType,DEFAULT_DEVICE_ID,CHAIN_KEY_SIZE,PQError,PQErrorCode}from'./types.js';export class PQSessionCipher{['store'];['identity']=null;constructor(a){this['store']=a;}async['ensureIdentity'](){if(this['identity'])return this['identity'];let a=await this['store']['getIdentityKeyPair'](),b=await this['store']['getEd25519KeyPair'](),c=await this['store']['getRegistrationId']();return(!a||!b||!c)&&(a=generateX25519KeyPair(),b=generateEd25519KeyPair(),c=deriveRegistrationId(a['publicKey']),await this['store']['setIdentityKeyPair'](a),await this['store']['setEd25519KeyPair'](b),await this['store']['setRegistrationId'](c)),this['identity']={'x25519KeyPair':a,'ed25519KeyPair':b,'registrationId':c},this['identity'];}async['generatePreKeyBundle'](a,b,c){const d=await this['ensureIdentity'](),e=generatePreKeyBundle(d['x25519KeyPair'],d['ed25519KeyPair'],a,b,c);await this['store']['setSignedPreKey'](a,e['signedPreKey']['keyPair']),await this['store']['setSignedPreKeySignature'](a,e['signedPreKey']['signature']);for(const f of e['oneTimePreKeys']){await this['store']['setOneTimePreKey'](f['keyId'],f['keyPair']);}return await this['store']['setPQPreKey'](b,e['pqPreKey']['keyPair']),await this['store']['setPQPreKeySignature'](b,e['pqPreKey']['signature']),e;}async['processPreKeyBundle'](a,b,c){const d=await this['ensureIdentity']();if(!verifyPreKeyBundle(c))throw new PQError(PQErrorCode['HANDSHAKE_FAILED'],'PreKey\x20bundle\x20signature\x20verification\x20failed');const e=pqxdhInitiate(d['x25519KeyPair'],d['ed25519KeyPair'],c),f=initRatchet(e['result']['rootKey'],e['result']['chainKey'],new Uint8Array(CHAIN_KEY_SIZE),e['result']['ourDHKeyPair'],e['result']['peerDHPublicKey']),g=initSPQR(),h={'pqxdhComplete':!![],'ratchetState':f,'spqrState':g,'peerIdentityKey':c['identityKey'],'peerRegistrationId':c['registrationId'],'peerDeviceId':b,'pendingInitialMessage':{'ephemeralPublicKey':e['initialMessage']['ephemeralPublicKey'],'mlkemCiphertext':e['initialMessage']['mlkemCiphertext'],'identityKey':e['initialMessage']['identityKey'],'signedPreKeyId':c['signedPreKey']['keyId'],'oneTimePreKeyId':c['oneTimePreKey']?.['keyId']??null,'pqPreKeyId':c['pqPreKey']['keyId']}};await this['store']['setPeerIdentity'](a,c['identityKey']),await this['saveSession'](a,b,h);}async['processInitialMessage'](a,b,c,d,e,f,g,h){const i=await this['ensureIdentity'](),j=await this['store']['getSignedPreKey'](f);if(!j)throw new PQError(PQErrorCode['HANDSHAKE_FAILED'],'Signed\x20pre-key\x20not\x20found');let k=null;g!==null&&(k=await this['store']['getOneTimePreKey'](g),k&&await this['store']['removeOneTimePreKey'](g));const l=await this['store']['getPQPreKey'](h);if(!l)throw new PQError(PQErrorCode['HANDSHAKE_FAILED'],'PQ\x20pre-key\x20not\x20found');const m=pqxdhReceive(i['x25519KeyPair'],j,k,l,c,e,d),n=initRatchet(m['rootKey'],new Uint8Array(CHAIN_KEY_SIZE),m['chainKey'],m['ourDHKeyPair'],m['peerDHPublicKey']),o=initSPQR(),p={'pqxdhComplete':!![],'ratchetState':n,'spqrState':o,'peerIdentityKey':e,'peerRegistrationId':0x0,'peerDeviceId':b};await this['store']['setPeerIdentity'](a,e),await this['saveSession'](a,b,p);}async['encryptMessage'](a,b,c=DEFAULT_DEVICE_ID){const d=await this['loadSession'](a,c);if(!d)throw new PQError(PQErrorCode['SESSION_NOT_FOUND'],'No\x20session\x20established');const {message:e,newState:f}=ratchetEncrypt(d['ratchetState'],b),g=f['sendingMessageCount']+f['previousSendingCount'],{chunk:h,newState:i}=spqrGetNextChunk(d['spqrState'],g);let j;if(h){const l=packChunk(h);j=concatBytes(new Uint8Array([0x1]),e['body'],l);}else j=concatBytes(new Uint8Array([0x0]),e['body']);const k=d['pendingInitialMessage']!==undefined;if(d['pendingInitialMessage']){const m=d['pendingInitialMessage'],n=m['oneTimePreKeyId']??0xffffffff,o=new Uint8Array(0x20+0x440+0x20+0x4+0x4+0x4),p=new DataView(o['buffer']);o['set'](m['ephemeralPublicKey'],0x0),o['set'](m['mlkemCiphertext'],0x20),o['set'](m['identityKey'],0x20+0x440),p['setUint32'](0x20+0x440+0x20,m['signedPreKeyId'],![]),p['setUint32'](0x20+0x440+0x20+0x4,n,![]),p['setUint32'](0x20+0x440+0x20+0x8,m['pqPreKeyId'],![]),j=concatBytes(o,j),d['pendingInitialMessage']=undefined;}return d['ratchetState']=f,d['spqrState']=i,await this['saveSession'](a,c,d),{'type':k?MessageType['PREKEY_MESSAGE']:MessageType['NORMAL_MESSAGE'],'body':j};}async['decryptMessage'](a,b,c=DEFAULT_DEVICE_ID){const d=0x20+0x440+0x20+0x4+0x4+0x4;let e=await this['loadSession'](a,c);if(!e&&b['length']>=d){const m=new DataView(b['buffer'],b['byteOffset'],b['byteLength']),n=b['slice'](0x0,0x20),o=b['slice'](0x20,0x20+0x440),p=b['slice'](0x20+0x440,0x20+0x440+0x20),q=m['getUint32'](0x20+0x440+0x20,![]),r=m['getUint32'](0x20+0x440+0x20+0x4,![]),s=m['getUint32'](0x20+0x440+0x20+0x8,![]),t=r===0xffffffff?null:r;await this['processInitialMessage'](a,c,n,o,p,q,t,s),b=b['slice'](d),e=await this['loadSession'](a,c);}if(!e)throw new PQError(PQErrorCode['SESSION_NOT_FOUND'],'No\x20session\x20established');if(b['length']<0x1)throw new PQError(PQErrorCode['DECRYPTION_FAILED'],'Message\x20body\x20too\x20short');const f=b[0x0]===0x1,g=b['slice'](0x1);let h=null;if(f){if(g['length']<SHARD_SIZE)throw new PQError(PQErrorCode['DECRYPTION_FAILED'],'SPQR\x20chunk\x20missing');h=g['slice'](g['length']-SHARD_SIZE);}const i=f?g['slice'](0x0,g['length']-SHARD_SIZE):g,{plaintext:j,newState:k}=ratchetDecrypt(e['ratchetState'],i);let l=e['spqrState'];if(h){const u=spqrReceiveChunk(l,h);l=u['newState'];if(u['shouldSendCT']&&u['peerPQPK']){const v=spqrOnPeerPQPKReceived(l,u['peerPQPK']);l=v['newState'];}}return e['ratchetState']=k,e['spqrState']=l,await this['saveSession'](a,c,e),j;}async['hasSession'](a,b=DEFAULT_DEVICE_ID){const c=await this['loadSession'](a,b);return c!==null&&c['pqxdhComplete'];}async['loadSession'](a,b){const c=await this['store']['getSession'](a,b);if(!c)return null;const d={'pqxdhComplete':c['pqxdhComplete'],'ratchetState':deserializeRatchetState(c['ratchetState']),'spqrState':deserializeSPQRState(c['spqrState']),'peerIdentityKey':base64ToBytes(c['peerIdentityKey']),'peerRegistrationId':c['peerRegistrationId'],'peerDeviceId':c['peerDeviceId']};return c['pendingInitialMessage']&&(d['pendingInitialMessage']={'ephemeralPublicKey':base64ToBytes(c['pendingInitialMessage']['ephemeralPublicKey']),'mlkemCiphertext':base64ToBytes(c['pendingInitialMessage']['mlkemCiphertext']),'identityKey':base64ToBytes(c['pendingInitialMessage']['identityKey']),'signedPreKeyId':c['pendingInitialMessage']['signedPreKeyId'],'oneTimePreKeyId':c['pendingInitialMessage']['oneTimePreKeyId'],'pqPreKeyId':c['pendingInitialMessage']['pqPreKeyId']}),d;}async['saveSession'](a,b,c){const d={'pqxdhComplete':c['pqxdhComplete'],'ratchetState':serializeRatchetState(c['ratchetState']),'spqrState':serializeSPQRState(c['spqrState']),'peerIdentityKey':bytesToBase64(c['peerIdentityKey']),'peerRegistrationId':c['peerRegistrationId'],'peerDeviceId':c['peerDeviceId']};c['pendingInitialMessage']&&(d['pendingInitialMessage']={'ephemeralPublicKey':bytesToBase64(c['pendingInitialMessage']['ephemeralPublicKey']),'mlkemCiphertext':bytesToBase64(c['pendingInitialMessage']['mlkemCiphertext']),'identityKey':bytesToBase64(c['pendingInitialMessage']['identityKey']),'signedPreKeyId':c['pendingInitialMessage']['signedPreKeyId'],'oneTimePreKeyId':c['pendingInitialMessage']['oneTimePreKeyId'],'pqPreKeyId':c['pendingInitialMessage']['pqPreKeyId']}),await this['store']['setSession'](a,b,d);}}
1
+ import{generateX25519KeyPair,concatBytes,deriveRegistrationId,bytesToBase64,base64ToBytes}from'./crypto.js';import{pqxdhInitiate,pqxdhReceive,generatePreKeyBundle,verifyPreKeyBundle}from'./pqxdh.js';import{initRatchet,ratchetEncrypt,ratchetDecrypt,serializeRatchetState,deserializeRatchetState}from'./ratchet.js';import{initSPQR,spqrGetNextChunk,spqrReceiveChunk,spqrOnPeerPQPKReceived,serializeSPQRState,deserializeSPQRState}from'./spqr.js';import{packChunk,SHARD_SIZE}from'./erasure.js';import{MessageType,DEFAULT_DEVICE_ID,CHAIN_KEY_SIZE,PQError,PQErrorCode}from'./types.js';export class PQSessionCipher{['store'];['identity']=null;['getFalcon512KeyPair'];constructor(a,b){this['store']=a,this['getFalcon512KeyPair']=b||(async()=>{throw new PQError(PQErrorCode['HANDSHAKE_FAILED'],'Falcon512\x20key\x20pair\x20not\x20available\x20for\x20signing');});}async['ensureIdentity'](){if(this['identity'])return this['identity'];let a=await this['store']['getIdentityKeyPair'](),b=await this['store']['getRegistrationId']();return(!a||!b)&&(a=generateX25519KeyPair(),b=deriveRegistrationId(a['publicKey']),await this['store']['setIdentityKeyPair'](a),await this['store']['setRegistrationId'](b)),this['identity']={'x25519KeyPair':a,'registrationId':b},this['identity'];}async['generatePreKeyBundle'](a,b,c){const d=await this['ensureIdentity'](),e=await this['getFalcon512KeyPair'](),f=generatePreKeyBundle(d['x25519KeyPair'],e,a,b,c);await this['store']['setSignedPreKey'](a,f['signedPreKey']['keyPair']),await this['store']['setSignedPreKeySignature'](a,f['signedPreKey']['signature']);for(const g of f['oneTimePreKeys']){await this['store']['setOneTimePreKey'](g['keyId'],g['keyPair']);}return await this['store']['setPQPreKey'](b,f['pqPreKey']['keyPair']),await this['store']['setPQPreKeySignature'](b,f['pqPreKey']['signature']),f;}async['processPreKeyBundle'](a,b,c){const d=await this['ensureIdentity']();if(!verifyPreKeyBundle(c))throw new PQError(PQErrorCode['HANDSHAKE_FAILED'],'PreKey\x20bundle\x20signature\x20verification\x20failed');const e=pqxdhInitiate(d['x25519KeyPair'],c),f=initRatchet(e['result']['rootKey'],e['result']['chainKey'],new Uint8Array(CHAIN_KEY_SIZE),e['result']['ourDHKeyPair'],e['result']['peerDHPublicKey']),g=initSPQR(),h={'pqxdhComplete':!![],'ratchetState':f,'spqrState':g,'peerIdentityKey':c['identityKey'],'peerRegistrationId':c['registrationId'],'peerDeviceId':b,'pendingInitialMessage':{'ephemeralPublicKey':e['initialMessage']['ephemeralPublicKey'],'mlkemCiphertext':e['initialMessage']['mlkemCiphertext'],'identityKey':e['initialMessage']['identityKey'],'signedPreKeyId':c['signedPreKey']['keyId'],'oneTimePreKeyId':c['oneTimePreKey']?.['keyId']??null,'pqPreKeyId':c['pqPreKey']['keyId']}};await this['store']['setPeerIdentity'](a,c['identityKey']),await this['saveSession'](a,b,h);}async['processInitialMessage'](a,b,c,d,e,f,g,h){const i=await this['ensureIdentity'](),j=await this['store']['getSignedPreKey'](f);if(!j)throw new PQError(PQErrorCode['HANDSHAKE_FAILED'],'Signed\x20pre-key\x20not\x20found');let k=null;g!==null&&(k=await this['store']['getOneTimePreKey'](g),k&&await this['store']['removeOneTimePreKey'](g));const l=await this['store']['getPQPreKey'](h);if(!l)throw new PQError(PQErrorCode['HANDSHAKE_FAILED'],'PQ\x20pre-key\x20not\x20found');const m=pqxdhReceive(i['x25519KeyPair'],j,k,l,c,e,d),n=initRatchet(m['rootKey'],new Uint8Array(CHAIN_KEY_SIZE),m['chainKey'],m['ourDHKeyPair'],m['peerDHPublicKey']),o=initSPQR(),p={'pqxdhComplete':!![],'ratchetState':n,'spqrState':o,'peerIdentityKey':e,'peerRegistrationId':0x0,'peerDeviceId':b};await this['store']['setPeerIdentity'](a,e),await this['saveSession'](a,b,p);}async['encryptMessage'](a,b,c=DEFAULT_DEVICE_ID){const d=await this['loadSession'](a,c);if(!d)throw new PQError(PQErrorCode['SESSION_NOT_FOUND'],'No\x20session\x20established');const {message:e,newState:f}=ratchetEncrypt(d['ratchetState'],b),g=f['sendingMessageCount']+f['previousSendingCount'],{chunk:h,newState:i}=spqrGetNextChunk(d['spqrState'],g);let j;if(h){const l=packChunk(h);j=concatBytes(new Uint8Array([0x1]),e['body'],l);}else j=concatBytes(new Uint8Array([0x0]),e['body']);const k=d['pendingInitialMessage']!==undefined;if(d['pendingInitialMessage']){const m=d['pendingInitialMessage'],n=m['oneTimePreKeyId']??0xffffffff,o=new Uint8Array(0x20+0x440+0x20+0x4+0x4+0x4),p=new DataView(o['buffer']);o['set'](m['ephemeralPublicKey'],0x0),o['set'](m['mlkemCiphertext'],0x20),o['set'](m['identityKey'],0x20+0x440),p['setUint32'](0x20+0x440+0x20,m['signedPreKeyId'],![]),p['setUint32'](0x20+0x440+0x20+0x4,n,![]),p['setUint32'](0x20+0x440+0x20+0x8,m['pqPreKeyId'],![]),j=concatBytes(o,j),d['pendingInitialMessage']=undefined;}return d['ratchetState']=f,d['spqrState']=i,await this['saveSession'](a,c,d),{'type':k?MessageType['PREKEY_MESSAGE']:MessageType['NORMAL_MESSAGE'],'body':j};}async['decryptMessage'](a,b,c=DEFAULT_DEVICE_ID){const d=0x20+0x440+0x20+0x4+0x4+0x4;let e=await this['loadSession'](a,c);if(!e&&b['length']>=d){const m=new DataView(b['buffer'],b['byteOffset'],b['byteLength']),n=b['slice'](0x0,0x20),o=b['slice'](0x20,0x20+0x440),p=b['slice'](0x20+0x440,0x20+0x440+0x20),q=m['getUint32'](0x20+0x440+0x20,![]),r=m['getUint32'](0x20+0x440+0x20+0x4,![]),s=m['getUint32'](0x20+0x440+0x20+0x8,![]),t=r===0xffffffff?null:r;await this['processInitialMessage'](a,c,n,o,p,q,t,s),b=b['slice'](d),e=await this['loadSession'](a,c);}if(!e)throw new PQError(PQErrorCode['SESSION_NOT_FOUND'],'No\x20session\x20established');if(b['length']<0x1)throw new PQError(PQErrorCode['DECRYPTION_FAILED'],'Message\x20body\x20too\x20short');const f=b[0x0]===0x1,g=b['slice'](0x1);let h=null;if(f){if(g['length']<SHARD_SIZE)throw new PQError(PQErrorCode['DECRYPTION_FAILED'],'SPQR\x20chunk\x20missing');h=g['slice'](g['length']-SHARD_SIZE);}const i=f?g['slice'](0x0,g['length']-SHARD_SIZE):g,{plaintext:j,newState:k}=ratchetDecrypt(e['ratchetState'],i);let l=e['spqrState'];if(h){const u=spqrReceiveChunk(l,h);l=u['newState'];if(u['shouldSendCT']&&u['peerPQPK']){const v=spqrOnPeerPQPKReceived(l,u['peerPQPK']);l=v['newState'];}}return e['ratchetState']=k,e['spqrState']=l,await this['saveSession'](a,c,e),j;}async['hasSession'](a,b=DEFAULT_DEVICE_ID){const c=await this['loadSession'](a,b);return c!==null&&c['pqxdhComplete'];}async['loadSession'](a,b){const c=await this['store']['getSession'](a,b);if(!c)return null;const d={'pqxdhComplete':c['pqxdhComplete'],'ratchetState':deserializeRatchetState(c['ratchetState']),'spqrState':deserializeSPQRState(c['spqrState']),'peerIdentityKey':base64ToBytes(c['peerIdentityKey']),'peerRegistrationId':c['peerRegistrationId'],'peerDeviceId':c['peerDeviceId']};return c['pendingInitialMessage']&&(d['pendingInitialMessage']={'ephemeralPublicKey':base64ToBytes(c['pendingInitialMessage']['ephemeralPublicKey']),'mlkemCiphertext':base64ToBytes(c['pendingInitialMessage']['mlkemCiphertext']),'identityKey':base64ToBytes(c['pendingInitialMessage']['identityKey']),'signedPreKeyId':c['pendingInitialMessage']['signedPreKeyId'],'oneTimePreKeyId':c['pendingInitialMessage']['oneTimePreKeyId'],'pqPreKeyId':c['pendingInitialMessage']['pqPreKeyId']}),d;}async['saveSession'](a,b,c){const d={'pqxdhComplete':c['pqxdhComplete'],'ratchetState':serializeRatchetState(c['ratchetState']),'spqrState':serializeSPQRState(c['spqrState']),'peerIdentityKey':bytesToBase64(c['peerIdentityKey']),'peerRegistrationId':c['peerRegistrationId'],'peerDeviceId':c['peerDeviceId']};c['pendingInitialMessage']&&(d['pendingInitialMessage']={'ephemeralPublicKey':bytesToBase64(c['pendingInitialMessage']['ephemeralPublicKey']),'mlkemCiphertext':bytesToBase64(c['pendingInitialMessage']['mlkemCiphertext']),'identityKey':bytesToBase64(c['pendingInitialMessage']['identityKey']),'signedPreKeyId':c['pendingInitialMessage']['signedPreKeyId'],'oneTimePreKeyId':c['pendingInitialMessage']['oneTimePreKeyId'],'pqPreKeyId':c['pendingInitialMessage']['pqPreKeyId']}),await this['store']['setSession'](a,b,d);}}
@@ -1 +1 @@
1
- import{generateMLKEMKeyPair,mlkemEncapsulate,mlkemDecapsulate,hkdfDerive,concatBytes}from'./crypto.js';import{encodeShards,decodeShards,unpackChunk,DATA_SHARDS}from'./erasure.js';import{CHAIN_KEY_SIZE,MESSAGE_KEY_SIZE,MLKEM_PUBLIC_KEY_SIZE,MLKEM_CIPHERTEXT_SIZE}from'./types.js';const SPQR_CYCLE_INTERVAL=0x32;export function initSPQR(){return{'cycleId':0x0,'sendingPQKeys':null,'sendingChunks':[],'sendingChunkIndex':0x0,'sendingPhase':'idle','receivedChunks':new Map(),'receivingPhase':'idle','expectedTotalChunks':0x0,'receivedSharedSecret':null,'currentSPQRKey':new Uint8Array(MESSAGE_KEY_SIZE),'spqrChainKey':new Uint8Array(CHAIN_KEY_SIZE),'spqrMessageCount':0x0};}export function spqrGetNextChunk(a,b){const c=cloneSPQRState(a);if(c['sendingPhase']==='idle'&&b>0x0&&b%SPQR_CYCLE_INTERVAL===0x0){c['cycleId']+=0x1,c['sendingPQKeys']=generateMLKEMKeyPair(),c['sendingPhase']='sending_pk';const f=encodeShards(c['sendingPQKeys']['publicKey']);c['sendingChunks']=f,c['sendingChunkIndex']=0x0;}if(c['sendingPhase']==='idle')return{'chunk':null,'newState':c};if(c['sendingChunkIndex']>=c['sendingChunks']['length']){if(c['sendingPhase']==='sending_pk')c['sendingPhase']='sending_ct_no_pk',c['sendingChunkIndex']=0x0,c['sendingChunks']=[];else{if(c['sendingPhase']==='sending_ct_no_pk'||c['sendingPhase']==='sending_ct_pk')return c['sendingPhase']='idle',c['sendingPQKeys']=null,c['sendingChunks']=[],c['sendingChunkIndex']=0x0,{'chunk':null,'newState':c};}}if((c['sendingPhase']==='sending_ct_no_pk'||c['sendingPhase']==='sending_ct_pk')&&c['sendingChunks']['length']===0x0)return{'chunk':null,'newState':c};const d=c['sendingChunks'][c['sendingChunkIndex']],e={'cycleId':c['cycleId'],'chunkIndex':c['sendingChunkIndex'],'totalChunks':c['sendingChunks']['length'],'data':d};return c['sendingChunkIndex']+=0x1,{'chunk':e,'newState':c};}export function spqrProcessReceivedChunks(a,b){const c=cloneSPQRState(a);for(const d of b){c['receivingPhase']==='idle'&&(c['receivingPhase']='receiving_ct',c['expectedTotalChunks']=d['totalChunks'],c['receivedChunks']=new Map());if(d['cycleId']!==c['cycleId'])continue;c['receivedChunks']['set'](d['chunkIndex'],d['data']);}if(c['receivingPhase']==='receiving_ct'&&c['receivedChunks']['size']>=DATA_SHARDS){const e=decodeShards(c['receivedChunks'],c['expectedTotalChunks']),f=e['slice'](0x0,MLKEM_CIPHERTEXT_SIZE);if(c['sendingPQKeys']){const g=mlkemDecapsulate(f,c['sendingPQKeys']['secretKey']);return c['receivedSharedSecret']=g,c['currentSPQRKey']=hkdfDerive(concatBytes(c['currentSPQRKey'],g),new TextEncoder()['encode']('WowokSPQRUpdate'),MESSAGE_KEY_SIZE),c['receivingPhase']='done',c['receivedChunks']=new Map(),{'newState':c,'completed':!![]};}}return{'newState':c,'completed':![]};}export function spqrOnPeerPQPKReceived(a,b){const c=cloneSPQRState(a),{ciphertext:d,sharedSecret:e}=mlkemEncapsulate(b);c['currentSPQRKey']=hkdfDerive(concatBytes(c['currentSPQRKey'],e),new TextEncoder()['encode']('WowokSPQRUpdate'),MESSAGE_KEY_SIZE);const f=encodeShards(d);return c['sendingChunks']=f,c['sendingChunkIndex']=0x0,c['sendingPhase']='sending_ct_pk',{'newState':c,'ctChunks':f};}export function spqrReceiveChunk(a,b){const c=cloneSPQRState(a),d=unpackChunk(b);c['receivingPhase']==='idle'&&(c['receivingPhase']='receiving_pk',c['expectedTotalChunks']=d['totalChunks'],c['receivedChunks']=new Map(),c['cycleId']=d['cycleId']);if(d['cycleId']!==c['cycleId'])return{'newState':c,'peerPQPKReady':![],'peerPQPK':null,'shouldSendCT':![]};c['receivedChunks']['set'](d['chunkIndex'],d['data']);if(c['receivingPhase']==='receiving_pk'&&c['receivedChunks']['size']>=DATA_SHARDS){const e=decodeShards(c['receivedChunks'],c['expectedTotalChunks']),f=e['slice'](0x0,MLKEM_PUBLIC_KEY_SIZE);return c['receivingPhase']='receiving_ct',c['receivedChunks']=new Map(),{'newState':c,'peerPQPKReady':!![],'peerPQPK':f,'shouldSendCT':!![]};}if(c['receivingPhase']==='receiving_ct'&&c['receivedChunks']['size']>=DATA_SHARDS){const g=decodeShards(c['receivedChunks'],c['expectedTotalChunks']),h=g['slice'](0x0,MLKEM_CIPHERTEXT_SIZE);if(c['sendingPQKeys']){const i=mlkemDecapsulate(h,c['sendingPQKeys']['secretKey']);c['currentSPQRKey']=hkdfDerive(concatBytes(c['currentSPQRKey'],i),new TextEncoder()['encode']('WowokSPQRUpdate'),MESSAGE_KEY_SIZE),c['receivingPhase']='done',c['receivedChunks']=new Map(),c['sendingPQKeys']=null;}return{'newState':c,'peerPQPKReady':![],'peerPQPK':null,'shouldSendCT':![]};}return{'newState':c,'peerPQPKReady':![],'peerPQPK':null,'shouldSendCT':![]};}export function spqrGetCurrentKey(a){return a['currentSPQRKey'];}function cloneSPQRState(a){return{'cycleId':a['cycleId'],'sendingPQKeys':a['sendingPQKeys']?{'publicKey':new Uint8Array(a['sendingPQKeys']['publicKey']),'secretKey':new Uint8Array(a['sendingPQKeys']['secretKey'])}:null,'sendingChunks':a['sendingChunks']['map'](b=>new Uint8Array(b)),'sendingChunkIndex':a['sendingChunkIndex'],'sendingPhase':a['sendingPhase'],'receivedChunks':new Map(a['receivedChunks']),'receivingPhase':a['receivingPhase'],'expectedTotalChunks':a['expectedTotalChunks'],'receivedSharedSecret':a['receivedSharedSecret']?new Uint8Array(a['receivedSharedSecret']):null,'currentSPQRKey':new Uint8Array(a['currentSPQRKey']),'spqrChainKey':new Uint8Array(a['spqrChainKey']),'spqrMessageCount':a['spqrMessageCount']};}export function serializeSPQRState(a){const b={};for(const [c,d]of a['receivedChunks']){b[c['toString']()]=Buffer['from'](d)['toString']('base64');}return{'cycleId':a['cycleId'],'sendingPQPublicKey':a['sendingPQKeys']?Buffer['from'](a['sendingPQKeys']['publicKey'])['toString']('base64'):null,'sendingPQSecretKey':a['sendingPQKeys']?Buffer['from'](a['sendingPQKeys']['secretKey'])['toString']('base64'):null,'sendingChunks':a['sendingChunks']['map'](e=>Buffer['from'](e)['toString']('base64')),'sendingChunkIndex':a['sendingChunkIndex'],'sendingPhase':a['sendingPhase'],'receivedChunks':b,'receivingPhase':a['receivingPhase'],'expectedTotalChunks':a['expectedTotalChunks'],'receivedSharedSecret':a['receivedSharedSecret']?Buffer['from'](a['receivedSharedSecret'])['toString']('base64'):null,'currentSPQRKey':Buffer['from'](a['currentSPQRKey'])['toString']('base64'),'spqrChainKey':Buffer['from'](a['spqrChainKey'])['toString']('base64'),'spqrMessageCount':a['spqrMessageCount']};}export function deserializeSPQRState(a){const b=new Map();for(const [c,d]of Object['entries'](a['receivedChunks'])){b['set'](parseInt(c),new Uint8Array(Buffer['from'](d,'base64')));}return{'cycleId':a['cycleId'],'sendingPQKeys':a['sendingPQPublicKey']&&a['sendingPQSecretKey']?{'publicKey':new Uint8Array(Buffer['from'](a['sendingPQPublicKey'],'base64')),'secretKey':new Uint8Array(Buffer['from'](a['sendingPQSecretKey'],'base64'))}:null,'sendingChunks':a['sendingChunks']['map'](e=>new Uint8Array(Buffer['from'](e,'base64'))),'sendingChunkIndex':a['sendingChunkIndex'],'sendingPhase':a['sendingPhase'],'receivedChunks':b,'receivingPhase':a['receivingPhase'],'expectedTotalChunks':a['expectedTotalChunks'],'receivedSharedSecret':a['receivedSharedSecret']?new Uint8Array(Buffer['from'](a['receivedSharedSecret'],'base64')):null,'currentSPQRKey':new Uint8Array(Buffer['from'](a['currentSPQRKey'],'base64')),'spqrChainKey':new Uint8Array(Buffer['from'](a['spqrChainKey'],'base64')),'spqrMessageCount':a['spqrMessageCount']};}
1
+ import{generateMLKEMKeyPair,mlkemEncapsulate,mlkemDecapsulate,hkdfDerive,concatBytes}from'./crypto.js';import{encodeShards,decodeShards,unpackChunk,DATA_SHARDS}from'./erasure.js';import{CHAIN_KEY_SIZE,MESSAGE_KEY_SIZE,MLKEM_PUBLIC_KEY_SIZE,MLKEM_CIPHERTEXT_SIZE}from'./types.js';const SPQR_CYCLE_INTERVAL=0x32;export function initSPQR(){return{'cycleId':0x0,'sendingPQKeys':null,'sendingChunks':[],'sendingChunkIndex':0x0,'sendingPhase':'idle','receivedChunks':new Map(),'receivingPhase':'idle','expectedTotalChunks':0x0,'receivedSharedSecret':null,'currentSPQRKey':new Uint8Array(MESSAGE_KEY_SIZE),'spqrChainKey':new Uint8Array(CHAIN_KEY_SIZE),'spqrMessageCount':0x0};}export function spqrGetNextChunk(a,b){const c=cloneSPQRState(a);if(c['sendingPhase']==='idle'&&b>0x0&&b%SPQR_CYCLE_INTERVAL===0x0){c['cycleId']+=0x1,c['sendingPQKeys']=generateMLKEMKeyPair(),c['sendingPhase']='sending_pk';const f=encodeShards(c['sendingPQKeys']['publicKey']);c['sendingChunks']=f,c['sendingChunkIndex']=0x0;}if(c['sendingPhase']==='idle')return{'chunk':null,'newState':c};if(c['sendingChunkIndex']>=c['sendingChunks']['length']){if(c['sendingPhase']==='sending_pk')c['sendingPhase']='waiting_for_ct',c['sendingChunkIndex']=0x0,c['sendingChunks']=[];else{if(c['sendingPhase']==='sending_ct_pk')return c['sendingPhase']='idle',c['sendingPQKeys']=null,c['sendingChunks']=[],c['sendingChunkIndex']=0x0,{'chunk':null,'newState':c};}}if(c['sendingPhase']==='waiting_for_ct')return{'chunk':null,'newState':c};const d=c['sendingChunks'][c['sendingChunkIndex']],e={'cycleId':c['cycleId'],'chunkIndex':c['sendingChunkIndex'],'totalChunks':c['sendingChunks']['length'],'data':d};return c['sendingChunkIndex']+=0x1,{'chunk':e,'newState':c};}export function spqrProcessReceivedChunks(a,b){const c=cloneSPQRState(a);for(const d of b){c['receivingPhase']==='idle'&&(c['receivingPhase']='receiving_ct',c['expectedTotalChunks']=d['totalChunks'],c['receivedChunks']=new Map());if(d['cycleId']!==c['cycleId'])continue;c['receivedChunks']['set'](d['chunkIndex'],d['data']);}if(c['receivingPhase']==='receiving_ct'&&c['receivedChunks']['size']>=DATA_SHARDS){const e=decodeShards(c['receivedChunks'],c['expectedTotalChunks']),f=e['slice'](0x0,MLKEM_CIPHERTEXT_SIZE);if(c['sendingPQKeys']){const g=mlkemDecapsulate(f,c['sendingPQKeys']['secretKey']);return c['receivedSharedSecret']=g,c['currentSPQRKey']=hkdfDerive(concatBytes(c['currentSPQRKey'],g),new TextEncoder()['encode']('WowokSPQRUpdate'),MESSAGE_KEY_SIZE),c['receivingPhase']='done',c['receivedChunks']=new Map(),{'newState':c,'completed':!![]};}}return{'newState':c,'completed':![]};}export function spqrOnPeerPQPKReceived(a,b){const c=cloneSPQRState(a),{ciphertext:d,sharedSecret:e}=mlkemEncapsulate(b);c['currentSPQRKey']=hkdfDerive(concatBytes(c['currentSPQRKey'],e),new TextEncoder()['encode']('WowokSPQRUpdate'),MESSAGE_KEY_SIZE);const f=encodeShards(d);return c['sendingChunks']=f,c['sendingChunkIndex']=0x0,c['sendingPhase']='sending_ct_pk',{'newState':c,'ctChunks':f};}export function spqrReceiveChunk(a,b){const c=cloneSPQRState(a),d=unpackChunk(b);c['receivingPhase']==='idle'&&(c['receivingPhase']='receiving_pk',c['expectedTotalChunks']=d['totalChunks'],c['receivedChunks']=new Map(),c['cycleId']=d['cycleId']);if(d['cycleId']!==c['cycleId'])return{'newState':c,'peerPQPKReady':![],'peerPQPK':null,'shouldSendCT':![]};c['receivedChunks']['set'](d['chunkIndex'],d['data']);if(c['receivingPhase']==='receiving_pk'&&c['receivedChunks']['size']>=DATA_SHARDS){const e=decodeShards(c['receivedChunks'],c['expectedTotalChunks']),f=e['slice'](0x0,MLKEM_PUBLIC_KEY_SIZE);return c['receivingPhase']='receiving_ct',c['receivedChunks']=new Map(),{'newState':c,'peerPQPKReady':!![],'peerPQPK':f,'shouldSendCT':!![]};}if(c['receivingPhase']==='receiving_ct'&&c['receivedChunks']['size']>=DATA_SHARDS){const g=decodeShards(c['receivedChunks'],c['expectedTotalChunks']),h=g['slice'](0x0,MLKEM_CIPHERTEXT_SIZE);if(c['sendingPQKeys']){const i=mlkemDecapsulate(h,c['sendingPQKeys']['secretKey']);c['currentSPQRKey']=hkdfDerive(concatBytes(c['currentSPQRKey'],i),new TextEncoder()['encode']('WowokSPQRUpdate'),MESSAGE_KEY_SIZE),c['receivingPhase']='done',c['receivedChunks']=new Map(),c['sendingPQKeys']=null,c['sendingPhase']='idle',c['sendingChunks']=[],c['sendingChunkIndex']=0x0;}return{'newState':c,'peerPQPKReady':![],'peerPQPK':null,'shouldSendCT':![]};}return{'newState':c,'peerPQPKReady':![],'peerPQPK':null,'shouldSendCT':![]};}export function spqrGetCurrentKey(a){return a['currentSPQRKey'];}function cloneSPQRState(a){return{'cycleId':a['cycleId'],'sendingPQKeys':a['sendingPQKeys']?{'publicKey':new Uint8Array(a['sendingPQKeys']['publicKey']),'secretKey':new Uint8Array(a['sendingPQKeys']['secretKey'])}:null,'sendingChunks':a['sendingChunks']['map'](b=>new Uint8Array(b)),'sendingChunkIndex':a['sendingChunkIndex'],'sendingPhase':a['sendingPhase'],'receivedChunks':new Map(a['receivedChunks']),'receivingPhase':a['receivingPhase'],'expectedTotalChunks':a['expectedTotalChunks'],'receivedSharedSecret':a['receivedSharedSecret']?new Uint8Array(a['receivedSharedSecret']):null,'currentSPQRKey':new Uint8Array(a['currentSPQRKey']),'spqrChainKey':new Uint8Array(a['spqrChainKey']),'spqrMessageCount':a['spqrMessageCount']};}export function serializeSPQRState(a){const b={};for(const [c,d]of a['receivedChunks']){b[c['toString']()]=Buffer['from'](d)['toString']('base64');}return{'cycleId':a['cycleId'],'sendingPQPublicKey':a['sendingPQKeys']?Buffer['from'](a['sendingPQKeys']['publicKey'])['toString']('base64'):null,'sendingPQSecretKey':a['sendingPQKeys']?Buffer['from'](a['sendingPQKeys']['secretKey'])['toString']('base64'):null,'sendingChunks':a['sendingChunks']['map'](e=>Buffer['from'](e)['toString']('base64')),'sendingChunkIndex':a['sendingChunkIndex'],'sendingPhase':a['sendingPhase'],'receivedChunks':b,'receivingPhase':a['receivingPhase'],'expectedTotalChunks':a['expectedTotalChunks'],'receivedSharedSecret':a['receivedSharedSecret']?Buffer['from'](a['receivedSharedSecret'])['toString']('base64'):null,'currentSPQRKey':Buffer['from'](a['currentSPQRKey'])['toString']('base64'),'spqrChainKey':Buffer['from'](a['spqrChainKey'])['toString']('base64'),'spqrMessageCount':a['spqrMessageCount']};}export function deserializeSPQRState(a){const b=new Map();for(const [c,d]of Object['entries'](a['receivedChunks'])){b['set'](parseInt(c),new Uint8Array(Buffer['from'](d,'base64')));}return{'cycleId':a['cycleId'],'sendingPQKeys':a['sendingPQPublicKey']&&a['sendingPQSecretKey']?{'publicKey':new Uint8Array(Buffer['from'](a['sendingPQPublicKey'],'base64')),'secretKey':new Uint8Array(Buffer['from'](a['sendingPQSecretKey'],'base64'))}:null,'sendingChunks':a['sendingChunks']['map'](e=>new Uint8Array(Buffer['from'](e,'base64'))),'sendingChunkIndex':a['sendingChunkIndex'],'sendingPhase':a['sendingPhase'],'receivedChunks':b,'receivingPhase':a['receivingPhase'],'expectedTotalChunks':a['expectedTotalChunks'],'receivedSharedSecret':a['receivedSharedSecret']?new Uint8Array(Buffer['from'](a['receivedSharedSecret'],'base64')):null,'currentSPQRKey':new Uint8Array(Buffer['from'](a['currentSPQRKey'],'base64')),'spqrChainKey':new Uint8Array(Buffer['from'](a['spqrChainKey'],'base64')),'spqrMessageCount':a['spqrMessageCount']};}
@@ -1,5 +1,5 @@
1
1
  import type Database from "better-sqlite3";
2
- import type { X25519KeyPair, Ed25519KeyPair, MLKEMKeyPair, SerializedPQSessionState } from "./types.js";
2
+ import type { X25519KeyPair, MLKEMKeyPair, SerializedPQSessionState } from "./types.js";
3
3
  import type { PQSessionStore } from "./session.js";
4
4
  export declare class PQSessionStoreAdapter implements PQSessionStore {
5
5
  private db;
@@ -10,8 +10,6 @@ export declare class PQSessionStoreAdapter implements PQSessionStore {
10
10
  private delValue;
11
11
  getIdentityKeyPair(): Promise<X25519KeyPair | null>;
12
12
  setIdentityKeyPair(keyPair: X25519KeyPair): Promise<void>;
13
- getEd25519KeyPair(): Promise<Ed25519KeyPair | null>;
14
- setEd25519KeyPair(keyPair: Ed25519KeyPair): Promise<void>;
15
13
  getRegistrationId(): Promise<number | null>;
16
14
  setRegistrationId(id: number): Promise<void>;
17
15
  getSignedPreKey(keyId: number): Promise<X25519KeyPair | null>;
@@ -1 +1 @@
1
- const PQ_STORE_PREFIX='pq';function arrayBufferToBase64(a){return Buffer['from'](a)['toString']('base64');}function base64ToUint8Array(a){return new Uint8Array(Buffer['from'](a,'base64'));}export class PQSessionStoreAdapter{['db'];['userAddress'];constructor(a,b){this['db']=a,this['userAddress']=b;}['getValue'](a){const b=this['db']['prepare']('SELECT\x20value\x20FROM\x20signal_store\x20WHERE\x20store_type\x20=\x20?\x20AND\x20key\x20=\x20?')['get'](PQ_STORE_PREFIX,a);return b?.['value'];}['putValue'](a,b){this['db']['prepare']('INSERT\x20INTO\x20signal_store\x20(store_type,\x20key,\x20value,\x20updated_at)\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20VALUES\x20(?,\x20?,\x20?,\x20strftime(\x27%s\x27,\x20\x27now\x27))\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20ON\x20CONFLICT(store_type,\x20key)\x20DO\x20UPDATE\x20SET\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20value\x20=\x20excluded.value,\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20updated_at\x20=\x20excluded.updated_at')['run'](PQ_STORE_PREFIX,a,b);}['delValue'](a){this['db']['prepare']('DELETE\x20FROM\x20signal_store\x20WHERE\x20store_type\x20=\x20?\x20AND\x20key\x20=\x20?')['run'](PQ_STORE_PREFIX,a);}async['getIdentityKeyPair'](){const a=this['getValue']('identity_x25519');if(!a)return null;const b=JSON['parse'](a);return{'publicKey':base64ToUint8Array(b['pubKey']),'privateKey':base64ToUint8Array(b['privKey'])};}async['setIdentityKeyPair'](a){const b={'pubKey':arrayBufferToBase64(a['publicKey']),'privKey':arrayBufferToBase64(a['privateKey'])};this['putValue']('identity_x25519',JSON['stringify'](b));}async['getEd25519KeyPair'](){const a=this['getValue']('identity_ed25519');if(!a)return null;const b=JSON['parse'](a);return{'publicKey':base64ToUint8Array(b['pubKey']),'privateKey':base64ToUint8Array(b['privKey'])};}async['setEd25519KeyPair'](a){const b={'pubKey':arrayBufferToBase64(a['publicKey']),'privKey':arrayBufferToBase64(a['privateKey'])};this['putValue']('identity_ed25519',JSON['stringify'](b));}async['getRegistrationId'](){const a=this['getValue']('registration_id');return a?parseInt(a,0xa):null;}async['setRegistrationId'](a){this['putValue']('registration_id',a['toString']());}async['getSignedPreKey'](a){const b=this['getValue']('signed_prekey:'+a);if(!b)return null;const c=JSON['parse'](b);return{'publicKey':base64ToUint8Array(c['pubKey']),'privateKey':base64ToUint8Array(c['privKey'])};}async['setSignedPreKey'](a,b){const c={'pubKey':arrayBufferToBase64(b['publicKey']),'privKey':arrayBufferToBase64(b['privateKey'])};this['putValue']('signed_prekey:'+a,JSON['stringify'](c));}async['getSignedPreKeySignature'](a){const b=this['getValue']('signed_prekey_sig:'+a);return b?base64ToUint8Array(b):null;}async['setSignedPreKeySignature'](a,b){this['putValue']('signed_prekey_sig:'+a,arrayBufferToBase64(b));}async['getOneTimePreKey'](a){const b=this['getValue']('onetime_prekey:'+a);if(!b)return null;const c=JSON['parse'](b);return{'publicKey':base64ToUint8Array(c['pubKey']),'privateKey':base64ToUint8Array(c['privKey'])};}async['setOneTimePreKey'](a,b){const c={'pubKey':arrayBufferToBase64(b['publicKey']),'privKey':arrayBufferToBase64(b['privateKey'])};this['putValue']('onetime_prekey:'+a,JSON['stringify'](c));}async['removeOneTimePreKey'](a){this['delValue']('onetime_prekey:'+a);}async['getPQPreKey'](a){const b=this['getValue']('pq_prekey:'+a);if(!b)return null;const c=JSON['parse'](b);return{'publicKey':base64ToUint8Array(c['pubKey']),'secretKey':base64ToUint8Array(c['secKey'])};}async['setPQPreKey'](a,b){const c={'pubKey':arrayBufferToBase64(b['publicKey']),'secKey':arrayBufferToBase64(b['secretKey'])};this['putValue']('pq_prekey:'+a,JSON['stringify'](c));}async['getPQPreKeySignature'](a){const b=this['getValue']('pq_prekey_sig:'+a);return b?base64ToUint8Array(b):null;}async['setPQPreKeySignature'](a,b){this['putValue']('pq_prekey_sig:'+a,arrayBufferToBase64(b));}async['getSession'](a,b){const c='session:'+a+'.'+b,d=this['getValue'](c);if(!d)return null;return JSON['parse'](d);}async['setSession'](a,b,c){const d='session:'+a+'.'+b;this['putValue'](d,JSON['stringify'](c));}async['removeSession'](a,b){const c='session:'+a+'.'+b;this['delValue'](c);}async['getPeerIdentity'](a){const b=this['getValue']('peer_identity:'+a);return b?base64ToUint8Array(b):null;}async['setPeerIdentity'](a,b){this['putValue']('peer_identity:'+a,arrayBufferToBase64(b));}}
1
+ const PQ_STORE_PREFIX='pq';function arrayBufferToBase64(a){return Buffer['from'](a)['toString']('base64');}function base64ToUint8Array(a){return new Uint8Array(Buffer['from'](a,'base64'));}export class PQSessionStoreAdapter{['db'];['userAddress'];constructor(a,b){this['db']=a,this['userAddress']=b;}['getValue'](a){const b=this['db']['prepare']('SELECT\x20value\x20FROM\x20signal_store\x20WHERE\x20store_type\x20=\x20?\x20AND\x20key\x20=\x20?')['get'](PQ_STORE_PREFIX,a);return b?.['value'];}['putValue'](a,b){this['db']['prepare']('INSERT\x20INTO\x20signal_store\x20(store_type,\x20key,\x20value,\x20updated_at)\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20VALUES\x20(?,\x20?,\x20?,\x20strftime(\x27%s\x27,\x20\x27now\x27))\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20ON\x20CONFLICT(store_type,\x20key)\x20DO\x20UPDATE\x20SET\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20value\x20=\x20excluded.value,\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20updated_at\x20=\x20excluded.updated_at')['run'](PQ_STORE_PREFIX,a,b);}['delValue'](a){this['db']['prepare']('DELETE\x20FROM\x20signal_store\x20WHERE\x20store_type\x20=\x20?\x20AND\x20key\x20=\x20?')['run'](PQ_STORE_PREFIX,a);}async['getIdentityKeyPair'](){const a=this['getValue']('identity_x25519');if(!a)return null;const b=JSON['parse'](a);return{'publicKey':base64ToUint8Array(b['pubKey']),'privateKey':base64ToUint8Array(b['privKey'])};}async['setIdentityKeyPair'](a){const b={'pubKey':arrayBufferToBase64(a['publicKey']),'privKey':arrayBufferToBase64(a['privateKey'])};this['putValue']('identity_x25519',JSON['stringify'](b));}async['getRegistrationId'](){const a=this['getValue']('registration_id');return a?parseInt(a,0xa):null;}async['setRegistrationId'](a){this['putValue']('registration_id',a['toString']());}async['getSignedPreKey'](a){const b=this['getValue']('signed_prekey:'+a);if(!b)return null;const c=JSON['parse'](b);return{'publicKey':base64ToUint8Array(c['pubKey']),'privateKey':base64ToUint8Array(c['privKey'])};}async['setSignedPreKey'](a,b){const c={'pubKey':arrayBufferToBase64(b['publicKey']),'privKey':arrayBufferToBase64(b['privateKey'])};this['putValue']('signed_prekey:'+a,JSON['stringify'](c));}async['getSignedPreKeySignature'](a){const b=this['getValue']('signed_prekey_sig:'+a);return b?base64ToUint8Array(b):null;}async['setSignedPreKeySignature'](a,b){this['putValue']('signed_prekey_sig:'+a,arrayBufferToBase64(b));}async['getOneTimePreKey'](a){const b=this['getValue']('onetime_prekey:'+a);if(!b)return null;const c=JSON['parse'](b);return{'publicKey':base64ToUint8Array(c['pubKey']),'privateKey':base64ToUint8Array(c['privKey'])};}async['setOneTimePreKey'](a,b){const c={'pubKey':arrayBufferToBase64(b['publicKey']),'privKey':arrayBufferToBase64(b['privateKey'])};this['putValue']('onetime_prekey:'+a,JSON['stringify'](c));}async['removeOneTimePreKey'](a){this['delValue']('onetime_prekey:'+a);}async['getPQPreKey'](a){const b=this['getValue']('pq_prekey:'+a);if(!b)return null;const c=JSON['parse'](b);return{'publicKey':base64ToUint8Array(c['pubKey']),'secretKey':base64ToUint8Array(c['secKey'])};}async['setPQPreKey'](a,b){const c={'pubKey':arrayBufferToBase64(b['publicKey']),'secKey':arrayBufferToBase64(b['secretKey'])};this['putValue']('pq_prekey:'+a,JSON['stringify'](c));}async['getPQPreKeySignature'](a){const b=this['getValue']('pq_prekey_sig:'+a);return b?base64ToUint8Array(b):null;}async['setPQPreKeySignature'](a,b){this['putValue']('pq_prekey_sig:'+a,arrayBufferToBase64(b));}async['getSession'](a,b){const c='session:'+a+'.'+b,d=this['getValue'](c);if(!d)return null;return JSON['parse'](d);}async['setSession'](a,b,c){const d='session:'+a+'.'+b;this['putValue'](d,JSON['stringify'](c));}async['removeSession'](a,b){const c='session:'+a+'.'+b;this['delValue'](c);}async['getPeerIdentity'](a){const b=this['getValue']('peer_identity:'+a);return b?base64ToUint8Array(b):null;}async['setPeerIdentity'](a,b){this['putValue']('peer_identity:'+a,arrayBufferToBase64(b));}}
@@ -6,7 +6,7 @@ export interface X25519KeyPair {
6
6
  publicKey: Uint8Array;
7
7
  privateKey: Uint8Array;
8
8
  }
9
- export interface Ed25519KeyPair {
9
+ export interface Falcon512KeyPair {
10
10
  publicKey: Uint8Array;
11
11
  privateKey: Uint8Array;
12
12
  }
@@ -18,7 +18,7 @@ export interface PQPreKeyBundle {
18
18
  registrationId: number;
19
19
  deviceId: number;
20
20
  identityKey: Uint8Array;
21
- ed25519PublicKey: Uint8Array;
21
+ falcon512PublicKey: Uint8Array;
22
22
  signedPreKey: {
23
23
  keyId: number;
24
24
  publicKey: Uint8Array;
@@ -62,7 +62,7 @@ export declare enum MessageType {
62
62
  PREKEY_MESSAGE = 3,
63
63
  NORMAL_MESSAGE = 1
64
64
  }
65
- export type SPQRPhase = "idle" | "sending_pk" | "sending_ct_no_pk" | "sending_ct_pk" | "done";
65
+ export type SPQRPhase = "idle" | "sending_pk" | "waiting_for_ct" | "sending_ct_pk" | "done";
66
66
  export type SPQRReceivePhase = "idle" | "receiving_pk" | "receiving_ct" | "done";
67
67
  export interface SPQRState {
68
68
  cycleId: number;
@@ -102,7 +102,6 @@ export interface PQSessionState {
102
102
  }
103
103
  export interface PQIdentity {
104
104
  x25519KeyPair: X25519KeyPair;
105
- ed25519KeyPair: Ed25519KeyPair;
106
105
  registrationId: number;
107
106
  }
108
107
  export interface SerializedRatchetState {
@@ -167,7 +166,7 @@ export declare const ROOT_KEY_SIZE = 32;
167
166
  export declare const CHAIN_KEY_SIZE = 32;
168
167
  export declare const MESSAGE_KEY_SIZE = 32;
169
168
  export declare const DH_KEY_SIZE = 32;
170
- export declare const SIGNATURE_SIZE = 64;
169
+ export declare const SIGNATURE_SIZE = 666;
171
170
  export declare const MLKEM_PUBLIC_KEY_SIZE = 1184;
172
171
  export declare const MLKEM_SECRET_KEY_SIZE = 2400;
173
172
  export declare const MLKEM_CIPHERTEXT_SIZE = 1088;
@@ -1 +1 @@
1
- export var MessageType;(function(a){a[a['PREKEY_MESSAGE']=0x3]='PREKEY_MESSAGE',a[a['NORMAL_MESSAGE']=0x1]='NORMAL_MESSAGE';}(MessageType||(MessageType={})));export var PQErrorCode;(function(a){a['INVALID_KEY']='INVALID_KEY',a['HANDSHAKE_FAILED']='HANDSHAKE_FAILED',a['ENCRYPTION_FAILED']='ENCRYPTION_FAILED',a['DECRYPTION_FAILED']='DECRYPTION_FAILED',a['SESSION_NOT_FOUND']='SESSION_NOT_FOUND',a['SPQR_ERROR']='SPQR_ERROR',a['ERASURE_ERROR']='ERASURE_ERROR',a['SERIALIZATION_ERROR']='SERIALIZATION_ERROR';}(PQErrorCode||(PQErrorCode={})));export class PQError extends Error{['code'];constructor(a,b){super(b),this['code']=a,this['name']='PQError';}}export const DEFAULT_DEVICE_ID=0x1;export const ROOT_KEY_SIZE=0x20;export const CHAIN_KEY_SIZE=0x20;export const MESSAGE_KEY_SIZE=0x20;export const DH_KEY_SIZE=0x20;export const SIGNATURE_SIZE=0x40;export const MLKEM_PUBLIC_KEY_SIZE=0x4a0;export const MLKEM_SECRET_KEY_SIZE=0x960;export const MLKEM_CIPHERTEXT_SIZE=0x440;export const MLKEM_SHARED_SECRET_SIZE=0x20;export const AES_GCM_IV_SIZE=0xc;export const AES_GCM_TAG_SIZE=0x10;export const SPQR_CHUNK_DATA_SIZE=0x22;export const SPQR_CHUNK_HEADER_SIZE=0x8;export const SPQR_CHUNK_SIZE=SPQR_CHUNK_DATA_SIZE+SPQR_CHUNK_HEADER_SIZE;export const SPQR_DATA_CHUNKS=0x1c;export const SPQR_TOTAL_CHUNKS=0x38;
1
+ export var MessageType;(function(a){a[a['PREKEY_MESSAGE']=0x3]='PREKEY_MESSAGE',a[a['NORMAL_MESSAGE']=0x1]='NORMAL_MESSAGE';}(MessageType||(MessageType={})));export var PQErrorCode;(function(a){a['INVALID_KEY']='INVALID_KEY',a['HANDSHAKE_FAILED']='HANDSHAKE_FAILED',a['ENCRYPTION_FAILED']='ENCRYPTION_FAILED',a['DECRYPTION_FAILED']='DECRYPTION_FAILED',a['SESSION_NOT_FOUND']='SESSION_NOT_FOUND',a['SPQR_ERROR']='SPQR_ERROR',a['ERASURE_ERROR']='ERASURE_ERROR',a['SERIALIZATION_ERROR']='SERIALIZATION_ERROR';}(PQErrorCode||(PQErrorCode={})));export class PQError extends Error{['code'];constructor(a,b){super(b),this['code']=a,this['name']='PQError';}}export const DEFAULT_DEVICE_ID=0x1;export const ROOT_KEY_SIZE=0x20;export const CHAIN_KEY_SIZE=0x20;export const MESSAGE_KEY_SIZE=0x20;export const DH_KEY_SIZE=0x20;export const SIGNATURE_SIZE=0x29a;export const MLKEM_PUBLIC_KEY_SIZE=0x4a0;export const MLKEM_SECRET_KEY_SIZE=0x960;export const MLKEM_CIPHERTEXT_SIZE=0x440;export const MLKEM_SHARED_SECRET_SIZE=0x20;export const AES_GCM_IV_SIZE=0xc;export const AES_GCM_TAG_SIZE=0x10;export const SPQR_CHUNK_DATA_SIZE=0x22;export const SPQR_CHUNK_HEADER_SIZE=0x8;export const SPQR_CHUNK_SIZE=SPQR_CHUNK_DATA_SIZE+SPQR_CHUNK_HEADER_SIZE;export const SPQR_DATA_CHUNKS=0x1c;export const SPQR_TOTAL_CHUNKS=0x38;
@@ -1,11 +1,9 @@
1
1
  import { PQSessionCipher } from "./pq/index.js";
2
2
  import type { PQSessionStore } from "./pq/session.js";
3
- import type { Xed25519KeyPair, MessengerConfig, RemoteBundle } from "./types.js";
4
- import type { X25519KeyPair, Ed25519KeyPair } from "./pq/types.js";
3
+ import type { MessengerConfig, RemoteBundle } from "./types.js";
4
+ import type { X25519KeyPair } from "./pq/types.js";
5
5
  export interface LocalIdentity {
6
- xed25519: Xed25519KeyPair;
7
6
  x25519KeyPair: X25519KeyPair;
8
- ed25519KeyPair: Ed25519KeyPair;
9
7
  registrationId: number;
10
8
  }
11
9
  export interface EncryptedMessage {
@@ -19,10 +17,11 @@ export declare class MessengerSession {
19
17
  private serverClient;
20
18
  private config;
21
19
  private identity;
20
+ private userAddress;
22
21
  constructor(userAddress: string, config?: Partial<MessengerConfig>);
23
22
  get store(): PQSessionStore;
24
23
  get cipher(): PQSessionCipher;
25
- ensureIdentity(userAddress?: string): Promise<LocalIdentity>;
24
+ ensureIdentity(_userAddress?: string): Promise<LocalIdentity>;
26
25
  private deriveRegistrationId;
27
26
  registerDevice(userAddress: string): Promise<void>;
28
27
  private verifyRegistrationComplete;
@@ -1 +1 @@
1
- import{PQSessionCipher,PQSessionStoreAdapter}from'./pq/index.js';import{MessengerServerClient}from'./server.js';import{getDatabase}from'./storage.js';import{recoverXed25519FromX25519PrivateKey,bytesToBase64,base64ToBytes}from'./crypto.js';import{MessageType,DEFAULT_MESSENGER_CONFIG,MessengerError,MessengerErrorCode,DEFAULT_DEVICE_ID}from'./types.js';async function getAccount(){const {Account:a}=await import('../local/account.js');return a['Instance']();}export class MessengerSession{['pqStore'];['pqCipher'];['serverClient'];['config'];['identity']=null;constructor(a,b){this['config']={...DEFAULT_MESSENGER_CONFIG,...b},this['serverClient']=new MessengerServerClient(this['config']);const c=getDatabase(a);this['pqStore']=new PQSessionStoreAdapter(c,a),this['pqCipher']=new PQSessionCipher(this['pqStore']);}get['store'](){return this['pqStore'];}get['cipher'](){return this['pqCipher'];}async['ensureIdentity'](a){if(this['identity'])return this['identity'];const b=await this['pqStore']['getIdentityKeyPair'](),c=await this['pqStore']['getEd25519KeyPair'](),d=await this['pqStore']['getRegistrationId']();if(b&&c&&d){const k=recoverXed25519FromX25519PrivateKey(b['privateKey']);return this['identity']={'xed25519':k,'x25519KeyPair':b,'ed25519KeyPair':c,'registrationId':d},this['identity'];}if(!a)throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'userAddress\x20is\x20required\x20to\x20derive\x20identity');const {privateKey:e,publicKey:f}=await(await getAccount())['deriveX25519KeyPair'](a),g=this['deriveRegistrationId'](f),h={'publicKey':f,'privateKey':e},i=recoverXed25519FromX25519PrivateKey(e),j={'publicKey':i['ed25519PublicKey'],'privateKey':i['ed25519PrivateKey']};return await this['pqStore']['setIdentityKeyPair'](h),await this['pqStore']['setEd25519KeyPair'](j),await this['pqStore']['setRegistrationId'](g),this['identity']={'xed25519':i,'x25519KeyPair':h,'ed25519KeyPair':j,'registrationId':g},this['identity'];}['deriveRegistrationId'](a){const b=a[0x0]<<0x8|a[0x1];return b===0x0?0x1:b;}async['registerDevice'](a){const b=await this['ensureIdentity'](a),c=0x1,d=0x1;let e,f;const g=await this['pqStore']['getSignedPreKeySignature'](c),h=await this['pqStore']['getSignedPreKey'](c),i=await this['pqStore']['getPQPreKey'](d),j=await this['pqStore']['getPQPreKeySignature'](d);if(h&&g&&i&&j)e=h['publicKey'],f=g;else{const u=await this['pqCipher']['generatePreKeyBundle'](c,d,this['config']['prekey_count']);e=u['signedPreKey']['keyPair']['publicKey'],f=u['signedPreKey']['signature'];}const k=await this['generatePreKeyBatch'](this['config']['prekey_count'],a),l=await(await getAccount())['get'](a,![]);if(!l?.['pubkey'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'Account\x20not\x20found\x20for\x20'+a);const m=Date['now'](),n=this['generateNonce'](),o='register:'+l['pubkey']+':'+m+':'+n,p=await(await getAccount())['signData'](a,o),q=Buffer['from'](p['signature']['slice'](0x2),'hex'),r=await this['pqStore']['getPQPreKey'](d),s=await this['pqStore']['getPQPreKeySignature'](d),t={'userAddress':a,'deviceId':DEFAULT_DEVICE_ID,'registrationId':b['registrationId'],'identityKey':bytesToBase64(b['x25519KeyPair']['publicKey']),'ed25519PublicKey':bytesToBase64(b['ed25519KeyPair']['publicKey']),'signedPrekey':{'keyId':c,'publicKey':bytesToBase64(e),'signature':bytesToBase64(f)},'prekeys':k,'publicKey':l['pubkey'],'signatureScheme':'ED25519','signature':bytesToBase64(q),'timestamp':m,'nonce':n};r&&s&&(t['pqPrekey']={'keyId':d,'publicKey':bytesToBase64(r['publicKey']),'signature':bytesToBase64(s)}),await this['serverClient']['registerDevice'](t),await this['verifyRegistrationComplete'](a);}async['verifyRegistrationComplete'](a,b=0xa,c=0x1f4){for(let d=0x0;d<b;d++){try{const e=await this['serverClient']['getPrekeyStatus'](a);return;}catch(f){if(f?.['message']?.['includes']('404')||f?.['status']===0x194){if(d<b-0x1){await new Promise(g=>setTimeout(g,c));continue;}}throw f;}}throw new MessengerError(MessengerErrorCode['REGISTRATION_FAILED'],'Registration\x20verification\x20failed\x20after\x20'+b+'\x20attempts');}async['isDeviceRegistered'](a){try{const b=await this['pqStore']['getSignedPreKeySignature'](0x1);if(!b)return![];const c=await this['serverClient']['getPrekeyStatus'](a);return!![];}catch(d){if(d?.['message']?.['includes']('404')||d?.['status']===0x194)return![];return![];}}async['generatePreKeyBatch'](a,b){if(a<=0x0)return[];const c=[],{generateX25519KeyPair:d}=await import('./pq/crypto.js'),e=Math['floor'](Math['random']()*0x7fffff00);for(let f=0x0;f<a;f++){const g=e+f,h=await this['pqStore']['getOneTimePreKey'](g);if(h){const m=bytesToBase64(h['publicKey']),n=await(await getAccount())['signData'](b,h['publicKey']),o=Buffer['from'](n['signature']['slice'](0x2),'hex');c['push']({'keyId':g,'publicKey':m,'signature':bytesToBase64(o)});continue;}const j=d(),k=await(await getAccount())['signData'](b,j['publicKey']),l=Buffer['from'](k['signature']['slice'](0x2),'hex');await this['pqStore']['setOneTimePreKey'](g,j),c['push']({'keyId':g,'publicKey':bytesToBase64(j['publicKey']),'signature':bytesToBase64(l)});}return c;}async['ensurePreKeys'](a,b=![]){const c=await this['serverClient']['getPrekeyStatus'](a);if(!b&&c['currentCount']>=c['maxAllowed'])return;const d=c['maxAllowed']-c['currentCount'];if(d<=0x0)return;await this['ensureIdentity'](a);const e=await this['generatePreKeyBatch'](d,a);if(e['length']===0x0)return;const f=await(await getAccount())['get'](a,![]);if(!f?.['pubkey'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'Account\x20not\x20found\x20for\x20'+a);const g=Date['now'](),h=this['generateNonce'](),i='upload_prekeys:'+f['pubkey']+':'+g+':'+h,j=await(await getAccount())['signData'](a,i),k=Buffer['from'](j['signature']['slice'](0x2),'hex');await this['serverClient']['uploadPreKeys']({'userAddress':a,'prekeys':e,'publicKey':f['pubkey'],'signatureScheme':'ED25519','signature':bytesToBase64(k),'timestamp':g,'nonce':h});}['generateNonce'](){const a=new Uint8Array(0x10);return crypto['getRandomValues'](a),Array['from'](a,c=>c['toString'](0x10)['padStart'](0x2,'0'))['join']('');}async['establishSession'](a,b,c=DEFAULT_DEVICE_ID,d){const e=await this['pqCipher']['hasSession'](b,c);if(e)return;if(!d){const l=await(await getAccount())['get'](a,![]);if(!l?.['pubkey'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'Account\x20not\x20found\x20for\x20'+a);const m=Date['now'](),n=this['generateNonce'](),o=l['pubkey'],p='get_bundle:'+a+':'+m+':'+n,q=await(await getAccount())['signData'](a,p),r=Buffer['from'](q['signature']['slice'](0x2),'hex');d=await this['serverClient']['fetchRemoteBundle'](b,a,o,{'signatureScheme':'ED25519','signature':bytesToBase64(new Uint8Array(r)),'timestamp':m,'nonce':n},c);}const f=d['signedPrekey'];if(!f)throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'No\x20signed\x20prekey\x20available\x20for\x20'+b);const g=base64ToBytes(d['identityKey']),h=d['ed25519PublicKey']?base64ToBytes(d['ed25519PublicKey']):g,i=base64ToBytes(f['publicKey']),j=base64ToBytes(f['signature']),k={'registrationId':d['registrationId'],'deviceId':c,'identityKey':g,'ed25519PublicKey':h,'signedPreKey':{'keyId':f['keyId'],'publicKey':i,'signature':j},'pqPreKey':d['pqPreKey']?{'keyId':d['pqPreKey']['keyId'],'publicKey':base64ToBytes(d['pqPreKey']['publicKey']),'signature':base64ToBytes(d['pqPreKey']['signature'])}:undefined};if(d['oneTimePrekey']){const s=base64ToBytes(d['oneTimePrekey']['publicKey']);k['oneTimePreKey']={'keyId':d['oneTimePrekey']['keyId'],'publicKey':s};}if(d['pqPreKey']){const t=base64ToBytes(d['pqPreKey']['publicKey']),u=base64ToBytes(d['pqPreKey']['signature']);k['pqPreKey']={'keyId':d['pqPreKey']['keyId'],'publicKey':t,'signature':u};}await this['pqCipher']['processPreKeyBundle'](b,c,k);}async['encryptMessage'](a,b,c,d=DEFAULT_DEVICE_ID){let e=0x0;const f=0x5;while(e<=f){try{const g=await this['pqCipher']['hasSession'](b,d);!g&&(console['log']('[Session]\x20建立新会话\x20(尝试\x20'+(e+0x1)+'/'+(f+0x1)+')'),await this['establishSession'](a,b,d));const h=new TextEncoder(),i=h['encode'](c),j=await this['pqCipher']['encryptMessage'](b,i,d);return{'type':j['type'],'body':j['body']['buffer'],'registrationId':j['registrationId']};}catch(k){console['error']('[Session]\x20加密失败\x20(尝试\x20'+(e+0x1)+'/'+(f+0x1)+'):',k);if(e>=f)throw k;console['log']('[Session]\x20尝试删除旧会话并重新建立...');try{await this['pqStore']['removeSession'](b,d),e++,await new Promise(l=>setTimeout(l,0x64));}catch(l){console['error']('[Session]\x20重新建立会话失败:',l);throw k;}}}throw new MessengerError(MessengerErrorCode['ENCRYPTION_FAILED'],'Encryption\x20failed\x20after\x20multiple\x20attempts');}async['decryptMessage'](a,b,c,d,e=DEFAULT_DEVICE_ID){const f=new TextDecoder(),g=new Uint8Array(c);let h=0x0;const i=0x5,j=await this['pqCipher']['hasSession'](b,e);if(d!==MessageType['PREKEY_MESSAGE']&&!j){console['log']('[Session]\x20收到\x20WHISPER_MESSAGE\x20但无现有会话,需要等待\x20PREKEY_MESSAGE');throw new Error('收到\x20WHISPER_MESSAGE\x20但无现有会话,需要等待\x20PREKEY_MESSAGE');}while(h<=i){try{let k;if(d===MessageType['PREKEY_MESSAGE']){console['log']('[Session]\x20收到\x20PREKEY_MESSAGE,尝试解密\x20(尝试\x20'+(h+0x1)+'/'+(i+0x1)+')');try{return k=await this['pqCipher']['decryptMessage'](b,g,e),console['log']('[Session]\x20PREKEY_MESSAGE\x20解密成功!'),f['decode'](k);}catch(l){console['log']('[Session]\x20直接解密\x20PREKEY_MESSAGE\x20失败:\x20'+(l instanceof Error?l['message']:String(l)));if(j&&h===0x0){const m=a['toLowerCase'](),n=b['toLowerCase']();if(m<n){console['log']('[Session]\x20我的地址较小\x20('+m+'\x20<\x20'+n+'),保留我的会话,稍后重试');throw new Error('PREKEY\x20竞争:我的地址较小,保留我的会话');}else return console['log']('[Session]\x20我的地址较大\x20('+m+'\x20>\x20'+n+'),删除我的会话,用对方的\x20PREKEY_MESSAGE\x20建立新会话'),await this['pqStore']['removeSession'](b,e),console['log']('[Session]\x20已删除旧会话,重新尝试解密...'),k=await this['pqCipher']['decryptMessage'](b,g,e),console['log']('[Session]\x20PREKEY_MESSAGE\x20解密成功,新会话已建立'),f['decode'](k);}else throw l;}}else k=await this['pqCipher']['decryptMessage'](b,g,e);return f['decode'](k);}catch(o){console['error']('[Session\x20Debug]\x20解密失败\x20(尝试\x20'+(h+0x1)+'/'+(i+0x1)+'):'),console['error']('\x20\x20错误消息:\x20'+(o instanceof Error?o['message']:String(o))),console['error']('\x20\x20上下文:'),console['error']('\x20\x20\x20\x20-\x20myAddress:\x20'+a),console['error']('\x20\x20\x20\x20-\x20peerAddress:\x20'+b),console['error']('\x20\x20\x20\x20-\x20msgType:\x20'+d+'\x20('+(d===MessageType['PREKEY_MESSAGE']?'PREKEY':'WHISPER')+')');if(h>=i)throw o;console['log']('[Session]\x20尝试重新建立会话...');try{j&&(console['log']('[Session]\x20删除旧会话'),await this['pqStore']['removeSession'](b,e)),d===MessageType['PREKEY_MESSAGE']?console['log']('[Session]\x20收到的是\x20PREKEY_MESSAGE,等待发送方的\x20PreKey\x20即可重建会话'):console['log']('[Session]\x20收到的是\x20WHISPER_MESSAGE,需要让对方重新发送\x20PREKEY_MESSAGE'),h++,await new Promise(p=>setTimeout(p,0x64));}catch(p){console['error']('[Session]\x20重新建立会话失败:',p);throw o;}}}throw new MessengerError(MessengerErrorCode['DECRYPTION_FAILED'],'Decryption\x20failed\x20after\x20multiple\x20attempts');}async['getIdentityKey'](){const a=await this['ensureIdentity']();return bytesToBase64(a['x25519KeyPair']['publicKey']);}async['getRegistrationId'](){const a=await this['ensureIdentity']();return a['registrationId'];}}export class SessionStateManager{['store'];constructor(a){this['store']=a;}async['snapshotSession'](a,b){const c=await this['store']['getSession'](a,b);return{'sessionData':c?JSON['stringify'](c):null,'timestamp':Date['now']()};}async['rollbackSession'](a,b,c){if(c['sessionData']){const d=JSON['parse'](c['sessionData']);await this['store']['setSession'](a,b,d),console['log']('[SessionState]\x20回滚会话:\x20'+a+'.'+b);}else await this['store']['removeSession'](a,b),console['log']('[SessionState]\x20清除会话:\x20'+a+'.'+b);}async['commitSession'](a,b){console['log']('[SessionState]\x20提交新会话');}}export class DecryptionEngine{['sessionManager'];['store'];['cipher'];constructor(a){this['store']=a,this['cipher']=new PQSessionCipher(a),this['sessionManager']=new SessionStateManager(a);}async['decryptMessage'](a,b,c,d,e=DEFAULT_DEVICE_ID){const f=await this['sessionManager']['snapshotSession'](b,e);try{return d===MessageType['PREKEY_MESSAGE']?await this['handlePreKeyMessage'](a,b,c,e,f):await this['handleWhisperMessage'](a,b,c,e,f);}catch(g){return await this['sessionManager']['rollbackSession'](b,e,f),{'success':![],'sessionUpdated':![],'sessionRolledBack':!![],'messageType':d===MessageType['PREKEY_MESSAGE']?'PREKEY':'WHISPER','error':g instanceof Error?g['message']:String(g)};}}async['handlePreKeyMessage'](a,b,c,d,e){console['log']('[Decrypt]\x20处理\x20PREKEY_MESSAGE\x20from\x20'+b);const f=new TextDecoder(),g=new Uint8Array(c),h=await this['cipher']['decryptMessage'](b,g,d),i=f['decode'](h);console['log']('[Decrypt]\x20PREKEY_MESSAGE\x20解密成功'),await this['sessionManager']['commitSession'](b,d);const j=a['toLowerCase'](),k=b['toLowerCase']();return j<k?console['log']('[Decrypt]\x20小地址('+j+')保存接收会话用于解密,发送会话保持不变'):console['log']('[Decrypt]\x20大地址('+j+')接受新会话'),{'success':!![],'plaintext':i,'sessionUpdated':!![],'sessionRolledBack':![],'messageType':'PREKEY'};}async['handleWhisperMessage'](a,b,c,d,e){console['log']('[Decrypt]\x20处理\x20WHISPER_MESSAGE\x20from\x20'+b);const f=await this['cipher']['hasSession'](b,d);if(!f)throw new Error('No\x20session\x20for\x20WHISPER_MESSAGE');const g=new TextDecoder(),h=new Uint8Array(c),i=await this['cipher']['decryptMessage'](b,h,d),j=g['decode'](i);return console['log']('[Decrypt]\x20WHISPER_MESSAGE\x20解密成功'),{'success':!![],'plaintext':j,'sessionUpdated':!![],'sessionRolledBack':![],'messageType':'WHISPER'};}}
1
+ import{PQSessionCipher,PQSessionStoreAdapter}from'./pq/index.js';import{MessengerServerClient}from'./server.js';import{getDatabase}from'./storage.js';import{bytesToBase64,base64ToBytes}from'./crypto.js';import{MessageType,DEFAULT_MESSENGER_CONFIG,MessengerError,MessengerErrorCode,DEFAULT_DEVICE_ID}from'./types.js';async function getAccount(){const {Account:a}=await import('../local/account.js');return a['Instance']();}export class MessengerSession{['pqStore'];['pqCipher'];['serverClient'];['config'];['identity']=null;['userAddress'];constructor(a,b){this['config']={...DEFAULT_MESSENGER_CONFIG,...b},this['serverClient']=new MessengerServerClient(this['config']),this['userAddress']=a;const c=getDatabase(a);this['pqStore']=new PQSessionStoreAdapter(c,a),this['pqCipher']=new PQSessionCipher(this['pqStore'],async()=>{const d=await getAccount(),e=await d['deriveX25519Identity'](a);return e['falcon512KeyPair'];});}get['store'](){return this['pqStore'];}get['cipher'](){return this['pqCipher'];}async['ensureIdentity'](a){if(this['identity'])return this['identity'];const b=await this['pqStore']['getIdentityKeyPair'](),c=await this['pqStore']['getRegistrationId']();if(b&&c)return this['identity']={'x25519KeyPair':b,'registrationId':c},this['identity'];const d=await getAccount(),e=await d['deriveX25519Identity'](this['userAddress']);return await this['pqStore']['setIdentityKeyPair'](e['x25519KeyPair']),await this['pqStore']['setRegistrationId'](e['registrationId']),this['identity']={'x25519KeyPair':e['x25519KeyPair'],'registrationId':e['registrationId']},this['identity'];}['deriveRegistrationId'](a){const b=a[0x0]<<0x8|a[0x1];return b===0x0?0x1:b;}async['registerDevice'](a){const b=await this['ensureIdentity'](a),c=0x1,d=0x1;let e,f;const g=await this['pqStore']['getSignedPreKeySignature'](c),h=await this['pqStore']['getSignedPreKey'](c),i=await this['pqStore']['getPQPreKey'](d),j=await this['pqStore']['getPQPreKeySignature'](d);if(h&&g&&i&&j)e=h['publicKey'],f=g;else{const u=await this['pqCipher']['generatePreKeyBundle'](c,d,this['config']['prekey_count']);e=u['signedPreKey']['keyPair']['publicKey'],f=u['signedPreKey']['signature'];}const k=await this['generatePreKeyBatch'](this['config']['prekey_count'],a),l=await(await getAccount())['get'](a,![]);if(!l?.['pubkey'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'Account\x20not\x20found\x20for\x20'+a);const m=Date['now'](),n=this['generateNonce'](),o='register:'+l['pubkey']+':'+m+':'+n,p=await(await getAccount())['signData'](a,o),q=Buffer['from'](p['signature']['slice'](0x2),'hex'),r=await this['pqStore']['getPQPreKey'](d),s=await this['pqStore']['getPQPreKeySignature'](d),t={'userAddress':a,'deviceId':DEFAULT_DEVICE_ID,'registrationId':b['registrationId'],'identityKey':bytesToBase64(b['x25519KeyPair']['publicKey']),'falcon512PublicKey':bytesToBase64(base64ToBytes(l['pubkey'])['slice'](0x1)),'signedPrekey':{'keyId':c,'publicKey':bytesToBase64(e),'signature':bytesToBase64(f)},'prekeys':k,'publicKey':l['pubkey'],'signatureScheme':'Falcon512','signature':bytesToBase64(q),'timestamp':m,'nonce':n};r&&s&&(t['pqPrekey']={'keyId':d,'publicKey':bytesToBase64(r['publicKey']),'signature':bytesToBase64(s)}),await this['serverClient']['registerDevice'](t),await this['verifyRegistrationComplete'](a);}async['verifyRegistrationComplete'](a,b=0xa,c=0x1f4){for(let d=0x0;d<b;d++){try{const e=await this['serverClient']['getPrekeyStatus'](a);return;}catch(f){if(f?.['message']?.['includes']('404')||f?.['status']===0x194){if(d<b-0x1){await new Promise(g=>setTimeout(g,c));continue;}}throw f;}}throw new MessengerError(MessengerErrorCode['REGISTRATION_FAILED'],'Registration\x20verification\x20failed\x20after\x20'+b+'\x20attempts');}async['isDeviceRegistered'](a){try{const b=await this['pqStore']['getSignedPreKeySignature'](0x1);if(!b)return![];const c=await this['serverClient']['getPrekeyStatus'](a);return!![];}catch(d){if(d?.['message']?.['includes']('404')||d?.['status']===0x194)return![];return![];}}async['generatePreKeyBatch'](a,b){if(a<=0x0)return[];const c=[],{generateX25519KeyPair:d}=await import('./pq/crypto.js'),e=Math['floor'](Math['random']()*0x7fffff00);for(let f=0x0;f<a;f++){const g=e+f,h=await this['pqStore']['getOneTimePreKey'](g);if(h){const m=bytesToBase64(h['publicKey']),n=await(await getAccount())['signData'](b,h['publicKey']),o=Buffer['from'](n['signature']['slice'](0x2),'hex');c['push']({'keyId':g,'publicKey':m,'signature':bytesToBase64(o)});continue;}const j=d(),k=await(await getAccount())['signData'](b,j['publicKey']),l=Buffer['from'](k['signature']['slice'](0x2),'hex');await this['pqStore']['setOneTimePreKey'](g,j),c['push']({'keyId':g,'publicKey':bytesToBase64(j['publicKey']),'signature':bytesToBase64(l)});}return c;}async['ensurePreKeys'](a,b=![]){const c=await this['serverClient']['getPrekeyStatus'](a);if(!b&&c['currentCount']>=c['maxAllowed'])return;const d=c['maxAllowed']-c['currentCount'];if(d<=0x0)return;await this['ensureIdentity'](a);const e=await this['generatePreKeyBatch'](d,a);if(e['length']===0x0)return;const f=await(await getAccount())['get'](a,![]);if(!f?.['pubkey'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'Account\x20not\x20found\x20for\x20'+a);const g=Date['now'](),h=this['generateNonce'](),i='upload_prekeys:'+f['pubkey']+':'+g+':'+h,j=await(await getAccount())['signData'](a,i),k=Buffer['from'](j['signature']['slice'](0x2),'hex');await this['serverClient']['uploadPreKeys']({'userAddress':a,'prekeys':e,'publicKey':f['pubkey'],'signatureScheme':'Falcon512','signature':bytesToBase64(k),'timestamp':g,'nonce':h});}['generateNonce'](){const a=new Uint8Array(0x10);return crypto['getRandomValues'](a),Array['from'](a,c=>c['toString'](0x10)['padStart'](0x2,'0'))['join']('');}async['establishSession'](a,b,c=DEFAULT_DEVICE_ID,d){const e=await this['pqCipher']['hasSession'](b,c);if(e)return;if(!d){const l=await(await getAccount())['get'](a,![]);if(!l?.['pubkey'])throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'Account\x20not\x20found\x20for\x20'+a);const m=Date['now'](),n=this['generateNonce'](),o=l['pubkey'],p='get_bundle:'+a+':'+m+':'+n,q=await(await getAccount())['signData'](a,p),r=Buffer['from'](q['signature']['slice'](0x2),'hex');d=await this['serverClient']['fetchRemoteBundle'](b,a,o,{'signatureScheme':'Falcon512','signature':bytesToBase64(new Uint8Array(r)),'timestamp':m,'nonce':n},c);}const f=d['signedPrekey'];if(!f)throw new MessengerError(MessengerErrorCode['IDENTITY_NOT_FOUND'],'No\x20signed\x20prekey\x20available\x20for\x20'+b);const g=base64ToBytes(d['identityKey']),h=d['falcon512PublicKey']?base64ToBytes(d['falcon512PublicKey']):g,i=base64ToBytes(f['publicKey']),j=base64ToBytes(f['signature']),k={'registrationId':d['registrationId'],'deviceId':c,'identityKey':g,'falcon512PublicKey':h,'signedPreKey':{'keyId':f['keyId'],'publicKey':i,'signature':j},'pqPreKey':d['pqPreKey']?{'keyId':d['pqPreKey']['keyId'],'publicKey':base64ToBytes(d['pqPreKey']['publicKey']),'signature':base64ToBytes(d['pqPreKey']['signature'])}:undefined};if(d['oneTimePrekey']){const s=base64ToBytes(d['oneTimePrekey']['publicKey']);k['oneTimePreKey']={'keyId':d['oneTimePrekey']['keyId'],'publicKey':s};}if(d['pqPreKey']){const t=base64ToBytes(d['pqPreKey']['publicKey']),u=base64ToBytes(d['pqPreKey']['signature']);k['pqPreKey']={'keyId':d['pqPreKey']['keyId'],'publicKey':t,'signature':u};}await this['pqCipher']['processPreKeyBundle'](b,c,k);}async['encryptMessage'](a,b,c,d=DEFAULT_DEVICE_ID){let e=0x0;const f=0x5;while(e<=f){try{const g=await this['pqCipher']['hasSession'](b,d);!g&&(console['log']('[Session]\x20建立新会话\x20(尝试\x20'+(e+0x1)+'/'+(f+0x1)+')'),await this['establishSession'](a,b,d));const h=new TextEncoder(),i=h['encode'](c),j=await this['pqCipher']['encryptMessage'](b,i,d);return{'type':j['type'],'body':j['body']['buffer'],'registrationId':j['registrationId']};}catch(k){console['error']('[Session]\x20加密失败\x20(尝试\x20'+(e+0x1)+'/'+(f+0x1)+'):',k);if(e>=f)throw k;console['log']('[Session]\x20尝试删除旧会话并重新建立...');try{await this['pqStore']['removeSession'](b,d),e++,await new Promise(l=>setTimeout(l,0x64));}catch(l){console['error']('[Session]\x20重新建立会话失败:',l);throw k;}}}throw new MessengerError(MessengerErrorCode['ENCRYPTION_FAILED'],'Encryption\x20failed\x20after\x20multiple\x20attempts');}async['decryptMessage'](a,b,c,d,e=DEFAULT_DEVICE_ID){const f=new TextDecoder(),g=new Uint8Array(c);let h=0x0;const i=0x5,j=await this['pqCipher']['hasSession'](b,e);if(d!==MessageType['PREKEY_MESSAGE']&&!j){console['log']('[Session]\x20收到\x20WHISPER_MESSAGE\x20但无现有会话,需要等待\x20PREKEY_MESSAGE');throw new Error('收到\x20WHISPER_MESSAGE\x20但无现有会话,需要等待\x20PREKEY_MESSAGE');}while(h<=i){try{let k;if(d===MessageType['PREKEY_MESSAGE']){console['log']('[Session]\x20收到\x20PREKEY_MESSAGE,尝试解密\x20(尝试\x20'+(h+0x1)+'/'+(i+0x1)+')');try{return k=await this['pqCipher']['decryptMessage'](b,g,e),console['log']('[Session]\x20PREKEY_MESSAGE\x20解密成功!'),f['decode'](k);}catch(l){console['log']('[Session]\x20直接解密\x20PREKEY_MESSAGE\x20失败:\x20'+(l instanceof Error?l['message']:String(l)));if(j&&h===0x0){const m=a['toLowerCase'](),n=b['toLowerCase']();if(m<n){console['log']('[Session]\x20我的地址较小\x20('+m+'\x20<\x20'+n+'),保留我的会话,稍后重试');throw new Error('PREKEY\x20竞争:我的地址较小,保留我的会话');}else return console['log']('[Session]\x20我的地址较大\x20('+m+'\x20>\x20'+n+'),删除我的会话,用对方的\x20PREKEY_MESSAGE\x20建立新会话'),await this['pqStore']['removeSession'](b,e),console['log']('[Session]\x20已删除旧会话,重新尝试解密...'),k=await this['pqCipher']['decryptMessage'](b,g,e),console['log']('[Session]\x20PREKEY_MESSAGE\x20解密成功,新会话已建立'),f['decode'](k);}else throw l;}}else k=await this['pqCipher']['decryptMessage'](b,g,e);return f['decode'](k);}catch(o){console['error']('[Session\x20Debug]\x20解密失败\x20(尝试\x20'+(h+0x1)+'/'+(i+0x1)+'):'),console['error']('\x20\x20错误消息:\x20'+(o instanceof Error?o['message']:String(o))),console['error']('\x20\x20上下文:'),console['error']('\x20\x20\x20\x20-\x20myAddress:\x20'+a),console['error']('\x20\x20\x20\x20-\x20peerAddress:\x20'+b),console['error']('\x20\x20\x20\x20-\x20msgType:\x20'+d+'\x20('+(d===MessageType['PREKEY_MESSAGE']?'PREKEY':'WHISPER')+')');if(h>=i)throw o;console['log']('[Session]\x20尝试重新建立会话...');try{j&&(console['log']('[Session]\x20删除旧会话'),await this['pqStore']['removeSession'](b,e)),d===MessageType['PREKEY_MESSAGE']?console['log']('[Session]\x20收到的是\x20PREKEY_MESSAGE,等待发送方的\x20PreKey\x20即可重建会话'):console['log']('[Session]\x20收到的是\x20WHISPER_MESSAGE,需要让对方重新发送\x20PREKEY_MESSAGE'),h++,await new Promise(p=>setTimeout(p,0x64));}catch(p){console['error']('[Session]\x20重新建立会话失败:',p);throw o;}}}throw new MessengerError(MessengerErrorCode['DECRYPTION_FAILED'],'Decryption\x20failed\x20after\x20multiple\x20attempts');}async['getIdentityKey'](){const a=await this['ensureIdentity']();return bytesToBase64(a['x25519KeyPair']['publicKey']);}async['getRegistrationId'](){const a=await this['ensureIdentity']();return a['registrationId'];}}export class SessionStateManager{['store'];constructor(a){this['store']=a;}async['snapshotSession'](a,b){const c=await this['store']['getSession'](a,b);return{'sessionData':c?JSON['stringify'](c):null,'timestamp':Date['now']()};}async['rollbackSession'](a,b,c){if(c['sessionData']){const d=JSON['parse'](c['sessionData']);await this['store']['setSession'](a,b,d),console['log']('[SessionState]\x20回滚会话:\x20'+a+'.'+b);}else await this['store']['removeSession'](a,b),console['log']('[SessionState]\x20清除会话:\x20'+a+'.'+b);}async['commitSession'](a,b){console['log']('[SessionState]\x20提交新会话');}}export class DecryptionEngine{['sessionManager'];['store'];['cipher'];constructor(a){this['store']=a,this['cipher']=new PQSessionCipher(a),this['sessionManager']=new SessionStateManager(a);}async['decryptMessage'](a,b,c,d,e=DEFAULT_DEVICE_ID){const f=await this['sessionManager']['snapshotSession'](b,e);try{return d===MessageType['PREKEY_MESSAGE']?await this['handlePreKeyMessage'](a,b,c,e,f):await this['handleWhisperMessage'](a,b,c,e,f);}catch(g){return await this['sessionManager']['rollbackSession'](b,e,f),{'success':![],'sessionUpdated':![],'sessionRolledBack':!![],'messageType':d===MessageType['PREKEY_MESSAGE']?'PREKEY':'WHISPER','error':g instanceof Error?g['message']:String(g)};}}async['handlePreKeyMessage'](a,b,c,d,e){console['log']('[Decrypt]\x20处理\x20PREKEY_MESSAGE\x20from\x20'+b);const f=new TextDecoder(),g=new Uint8Array(c),h=await this['cipher']['decryptMessage'](b,g,d),i=f['decode'](h);console['log']('[Decrypt]\x20PREKEY_MESSAGE\x20解密成功'),await this['sessionManager']['commitSession'](b,d);const j=a['toLowerCase'](),k=b['toLowerCase']();return j<k?console['log']('[Decrypt]\x20小地址('+j+')保存接收会话用于解密,发送会话保持不变'):console['log']('[Decrypt]\x20大地址('+j+')接受新会话'),{'success':!![],'plaintext':i,'sessionUpdated':!![],'sessionRolledBack':![],'messageType':'PREKEY'};}async['handleWhisperMessage'](a,b,c,d,e){console['log']('[Decrypt]\x20处理\x20WHISPER_MESSAGE\x20from\x20'+b);const f=await this['cipher']['hasSession'](b,d);if(!f)throw new Error('No\x20session\x20for\x20WHISPER_MESSAGE');const g=new TextDecoder(),h=new Uint8Array(c),i=await this['cipher']['decryptMessage'](b,h,d),j=g['decode'](i);return console['log']('[Decrypt]\x20WHISPER_MESSAGE\x20解密成功'),{'success':!![],'plaintext':j,'sessionUpdated':!![],'sessionRolledBack':![],'messageType':'WHISPER'};}}