@unwanted/matrix-sdk-mini 34.12.0-2 → 34.12.0-4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (492) hide show
  1. package/git-revision.txt +1 -1
  2. package/lib/@types/global.d.js +0 -2
  3. package/lib/@types/global.d.js.map +1 -1
  4. package/lib/browser-index.d.ts.map +1 -1
  5. package/lib/browser-index.js +0 -11
  6. package/lib/browser-index.js.map +1 -1
  7. package/lib/client.d.ts +2 -1221
  8. package/lib/client.d.ts.map +1 -1
  9. package/lib/client.js +331 -2821
  10. package/lib/client.js.map +1 -1
  11. package/lib/embedded.d.ts +0 -22
  12. package/lib/embedded.d.ts.map +1 -1
  13. package/lib/embedded.js +24 -166
  14. package/lib/embedded.js.map +1 -1
  15. package/lib/event-mapper.d.ts.map +1 -1
  16. package/lib/event-mapper.js +0 -4
  17. package/lib/event-mapper.js.map +1 -1
  18. package/lib/matrix.d.ts +0 -19
  19. package/lib/matrix.d.ts.map +1 -1
  20. package/lib/matrix.js +1 -26
  21. package/lib/matrix.js.map +1 -1
  22. package/lib/models/MSC3089Branch.d.ts.map +1 -1
  23. package/lib/models/MSC3089Branch.js +0 -3
  24. package/lib/models/MSC3089Branch.js.map +1 -1
  25. package/lib/models/event.d.ts +0 -94
  26. package/lib/models/event.d.ts.map +1 -1
  27. package/lib/models/event.js +0 -274
  28. package/lib/models/event.js.map +1 -1
  29. package/lib/models/poll.d.ts.map +1 -1
  30. package/lib/models/poll.js +1 -5
  31. package/lib/models/poll.js.map +1 -1
  32. package/lib/models/relations-container.d.ts.map +1 -1
  33. package/lib/models/relations-container.js +1 -7
  34. package/lib/models/relations-container.js.map +1 -1
  35. package/lib/models/relations.d.ts +0 -1
  36. package/lib/models/relations.d.ts.map +1 -1
  37. package/lib/models/relations.js +0 -8
  38. package/lib/models/relations.js.map +1 -1
  39. package/lib/models/room-state.d.ts.map +1 -1
  40. package/lib/models/room-state.js +10 -26
  41. package/lib/models/room-state.js.map +1 -1
  42. package/lib/models/room.d.ts +0 -18
  43. package/lib/models/room.d.ts.map +1 -1
  44. package/lib/models/room.js +94 -148
  45. package/lib/models/room.js.map +1 -1
  46. package/lib/models/thread.d.ts.map +1 -1
  47. package/lib/models/thread.js +0 -1
  48. package/lib/models/thread.js.map +1 -1
  49. package/lib/sliding-sync-sdk.d.ts +2 -3
  50. package/lib/sliding-sync-sdk.d.ts.map +1 -1
  51. package/lib/sliding-sync-sdk.js +41 -90
  52. package/lib/sliding-sync-sdk.js.map +1 -1
  53. package/lib/sync.d.ts +0 -12
  54. package/lib/sync.d.ts.map +1 -1
  55. package/lib/sync.js +1 -73
  56. package/lib/sync.js.map +1 -1
  57. package/lib/testing.d.ts +0 -48
  58. package/lib/testing.d.ts.map +1 -1
  59. package/lib/testing.js +0 -105
  60. package/lib/testing.js.map +1 -1
  61. package/lib/types.d.ts +0 -1
  62. package/lib/types.d.ts.map +1 -1
  63. package/lib/types.js.map +1 -1
  64. package/package.json +1 -3
  65. package/src/@types/global.d.ts +0 -3
  66. package/src/browser-index.ts +0 -11
  67. package/src/client.ts +60 -2882
  68. package/src/embedded.ts +3 -130
  69. package/src/event-mapper.ts +0 -4
  70. package/src/matrix.ts +0 -28
  71. package/src/models/MSC3089Branch.ts +0 -3
  72. package/src/models/event.ts +0 -289
  73. package/src/models/poll.ts +0 -6
  74. package/src/models/relations-container.ts +1 -8
  75. package/src/models/relations.ts +0 -8
  76. package/src/models/room-state.ts +2 -8
  77. package/src/models/room.ts +0 -62
  78. package/src/models/thread.ts +0 -1
  79. package/src/sliding-sync-sdk.ts +2 -72
  80. package/src/sync.ts +1 -98
  81. package/src/testing.ts +0 -108
  82. package/src/types.ts +0 -1
  83. package/CHANGELOG.md +0 -5910
  84. package/lib/@types/AESEncryptedSecretStoragePayload.d.ts +0 -14
  85. package/lib/@types/AESEncryptedSecretStoragePayload.d.ts.map +0 -1
  86. package/lib/@types/AESEncryptedSecretStoragePayload.js +0 -1
  87. package/lib/@types/AESEncryptedSecretStoragePayload.js.map +0 -1
  88. package/lib/@types/crypto.d.ts +0 -47
  89. package/lib/@types/crypto.d.ts.map +0 -1
  90. package/lib/@types/crypto.js +0 -1
  91. package/lib/@types/crypto.js.map +0 -1
  92. package/lib/@types/matrix-sdk-crypto-wasm.d.js +0 -1
  93. package/lib/@types/matrix-sdk-crypto-wasm.d.js.map +0 -1
  94. package/lib/common-crypto/CryptoBackend.d.ts +0 -240
  95. package/lib/common-crypto/CryptoBackend.d.ts.map +0 -1
  96. package/lib/common-crypto/CryptoBackend.js +0 -73
  97. package/lib/common-crypto/CryptoBackend.js.map +0 -1
  98. package/lib/common-crypto/key-passphrase.d.ts +0 -14
  99. package/lib/common-crypto/key-passphrase.d.ts.map +0 -1
  100. package/lib/common-crypto/key-passphrase.js +0 -33
  101. package/lib/common-crypto/key-passphrase.js.map +0 -1
  102. package/lib/crypto/CrossSigning.d.ts +0 -184
  103. package/lib/crypto/CrossSigning.d.ts.map +0 -1
  104. package/lib/crypto/CrossSigning.js +0 -718
  105. package/lib/crypto/CrossSigning.js.map +0 -1
  106. package/lib/crypto/DeviceList.d.ts +0 -216
  107. package/lib/crypto/DeviceList.d.ts.map +0 -1
  108. package/lib/crypto/DeviceList.js +0 -892
  109. package/lib/crypto/DeviceList.js.map +0 -1
  110. package/lib/crypto/EncryptionSetup.d.ts +0 -152
  111. package/lib/crypto/EncryptionSetup.d.ts.map +0 -1
  112. package/lib/crypto/EncryptionSetup.js +0 -356
  113. package/lib/crypto/EncryptionSetup.js.map +0 -1
  114. package/lib/crypto/OlmDevice.d.ts +0 -457
  115. package/lib/crypto/OlmDevice.d.ts.map +0 -1
  116. package/lib/crypto/OlmDevice.js +0 -1241
  117. package/lib/crypto/OlmDevice.js.map +0 -1
  118. package/lib/crypto/OutgoingRoomKeyRequestManager.d.ts +0 -109
  119. package/lib/crypto/OutgoingRoomKeyRequestManager.d.ts.map +0 -1
  120. package/lib/crypto/OutgoingRoomKeyRequestManager.js +0 -415
  121. package/lib/crypto/OutgoingRoomKeyRequestManager.js.map +0 -1
  122. package/lib/crypto/RoomList.d.ts +0 -26
  123. package/lib/crypto/RoomList.d.ts.map +0 -1
  124. package/lib/crypto/RoomList.js +0 -71
  125. package/lib/crypto/RoomList.js.map +0 -1
  126. package/lib/crypto/SecretSharing.d.ts +0 -24
  127. package/lib/crypto/SecretSharing.d.ts.map +0 -1
  128. package/lib/crypto/SecretSharing.js +0 -194
  129. package/lib/crypto/SecretSharing.js.map +0 -1
  130. package/lib/crypto/SecretStorage.d.ts +0 -55
  131. package/lib/crypto/SecretStorage.d.ts.map +0 -1
  132. package/lib/crypto/SecretStorage.js +0 -118
  133. package/lib/crypto/SecretStorage.js.map +0 -1
  134. package/lib/crypto/aes.d.ts +0 -6
  135. package/lib/crypto/aes.d.ts.map +0 -1
  136. package/lib/crypto/aes.js +0 -24
  137. package/lib/crypto/aes.js.map +0 -1
  138. package/lib/crypto/algorithms/base.d.ts +0 -156
  139. package/lib/crypto/algorithms/base.d.ts.map +0 -1
  140. package/lib/crypto/algorithms/base.js +0 -187
  141. package/lib/crypto/algorithms/base.js.map +0 -1
  142. package/lib/crypto/algorithms/index.d.ts +0 -4
  143. package/lib/crypto/algorithms/index.d.ts.map +0 -1
  144. package/lib/crypto/algorithms/index.js +0 -20
  145. package/lib/crypto/algorithms/index.js.map +0 -1
  146. package/lib/crypto/algorithms/megolm.d.ts +0 -385
  147. package/lib/crypto/algorithms/megolm.d.ts.map +0 -1
  148. package/lib/crypto/algorithms/megolm.js +0 -1822
  149. package/lib/crypto/algorithms/megolm.js.map +0 -1
  150. package/lib/crypto/algorithms/olm.d.ts +0 -5
  151. package/lib/crypto/algorithms/olm.d.ts.map +0 -1
  152. package/lib/crypto/algorithms/olm.js +0 -299
  153. package/lib/crypto/algorithms/olm.js.map +0 -1
  154. package/lib/crypto/api.d.ts +0 -32
  155. package/lib/crypto/api.d.ts.map +0 -1
  156. package/lib/crypto/api.js +0 -22
  157. package/lib/crypto/api.js.map +0 -1
  158. package/lib/crypto/backup.d.ts +0 -227
  159. package/lib/crypto/backup.d.ts.map +0 -1
  160. package/lib/crypto/backup.js +0 -824
  161. package/lib/crypto/backup.js.map +0 -1
  162. package/lib/crypto/crypto.d.ts +0 -3
  163. package/lib/crypto/crypto.d.ts.map +0 -1
  164. package/lib/crypto/crypto.js +0 -19
  165. package/lib/crypto/crypto.js.map +0 -1
  166. package/lib/crypto/dehydration.d.ts +0 -34
  167. package/lib/crypto/dehydration.d.ts.map +0 -1
  168. package/lib/crypto/dehydration.js +0 -252
  169. package/lib/crypto/dehydration.js.map +0 -1
  170. package/lib/crypto/device-converter.d.ts +0 -9
  171. package/lib/crypto/device-converter.d.ts.map +0 -1
  172. package/lib/crypto/device-converter.js +0 -42
  173. package/lib/crypto/device-converter.js.map +0 -1
  174. package/lib/crypto/deviceinfo.d.ts +0 -99
  175. package/lib/crypto/deviceinfo.d.ts.map +0 -1
  176. package/lib/crypto/deviceinfo.js +0 -148
  177. package/lib/crypto/deviceinfo.js.map +0 -1
  178. package/lib/crypto/index.d.ts +0 -1209
  179. package/lib/crypto/index.d.ts.map +0 -1
  180. package/lib/crypto/index.js +0 -4097
  181. package/lib/crypto/index.js.map +0 -1
  182. package/lib/crypto/key_passphrase.d.ts +0 -14
  183. package/lib/crypto/key_passphrase.d.ts.map +0 -1
  184. package/lib/crypto/key_passphrase.js +0 -44
  185. package/lib/crypto/key_passphrase.js.map +0 -1
  186. package/lib/crypto/keybackup.d.ts +0 -18
  187. package/lib/crypto/keybackup.d.ts.map +0 -1
  188. package/lib/crypto/keybackup.js +0 -1
  189. package/lib/crypto/keybackup.js.map +0 -1
  190. package/lib/crypto/olmlib.d.ts +0 -129
  191. package/lib/crypto/olmlib.d.ts.map +0 -1
  192. package/lib/crypto/olmlib.js +0 -492
  193. package/lib/crypto/olmlib.js.map +0 -1
  194. package/lib/crypto/recoverykey.d.ts +0 -2
  195. package/lib/crypto/recoverykey.d.ts.map +0 -1
  196. package/lib/crypto/recoverykey.js +0 -19
  197. package/lib/crypto/recoverykey.js.map +0 -1
  198. package/lib/crypto/store/base.d.ts +0 -252
  199. package/lib/crypto/store/base.d.ts.map +0 -1
  200. package/lib/crypto/store/base.js +0 -64
  201. package/lib/crypto/store/base.js.map +0 -1
  202. package/lib/crypto/store/indexeddb-crypto-store-backend.d.ts +0 -187
  203. package/lib/crypto/store/indexeddb-crypto-store-backend.d.ts.map +0 -1
  204. package/lib/crypto/store/indexeddb-crypto-store-backend.js +0 -1145
  205. package/lib/crypto/store/indexeddb-crypto-store-backend.js.map +0 -1
  206. package/lib/crypto/store/indexeddb-crypto-store.d.ts +0 -432
  207. package/lib/crypto/store/indexeddb-crypto-store.d.ts.map +0 -1
  208. package/lib/crypto/store/indexeddb-crypto-store.js +0 -728
  209. package/lib/crypto/store/indexeddb-crypto-store.js.map +0 -1
  210. package/lib/crypto/store/localStorage-crypto-store.d.ts +0 -119
  211. package/lib/crypto/store/localStorage-crypto-store.d.ts.map +0 -1
  212. package/lib/crypto/store/localStorage-crypto-store.js +0 -531
  213. package/lib/crypto/store/localStorage-crypto-store.js.map +0 -1
  214. package/lib/crypto/store/memory-crypto-store.d.ts +0 -215
  215. package/lib/crypto/store/memory-crypto-store.d.ts.map +0 -1
  216. package/lib/crypto/store/memory-crypto-store.js +0 -622
  217. package/lib/crypto/store/memory-crypto-store.js.map +0 -1
  218. package/lib/crypto/verification/Base.d.ts +0 -105
  219. package/lib/crypto/verification/Base.d.ts.map +0 -1
  220. package/lib/crypto/verification/Base.js +0 -372
  221. package/lib/crypto/verification/Base.js.map +0 -1
  222. package/lib/crypto/verification/Error.d.ts +0 -35
  223. package/lib/crypto/verification/Error.d.ts.map +0 -1
  224. package/lib/crypto/verification/Error.js +0 -86
  225. package/lib/crypto/verification/Error.js.map +0 -1
  226. package/lib/crypto/verification/IllegalMethod.d.ts +0 -15
  227. package/lib/crypto/verification/IllegalMethod.d.ts.map +0 -1
  228. package/lib/crypto/verification/IllegalMethod.js +0 -43
  229. package/lib/crypto/verification/IllegalMethod.js.map +0 -1
  230. package/lib/crypto/verification/QRCode.d.ts +0 -51
  231. package/lib/crypto/verification/QRCode.d.ts.map +0 -1
  232. package/lib/crypto/verification/QRCode.js +0 -277
  233. package/lib/crypto/verification/QRCode.js.map +0 -1
  234. package/lib/crypto/verification/SAS.d.ts +0 -27
  235. package/lib/crypto/verification/SAS.d.ts.map +0 -1
  236. package/lib/crypto/verification/SAS.js +0 -485
  237. package/lib/crypto/verification/SAS.js.map +0 -1
  238. package/lib/crypto/verification/SASDecimal.d.ts +0 -8
  239. package/lib/crypto/verification/SASDecimal.d.ts.map +0 -1
  240. package/lib/crypto/verification/SASDecimal.js +0 -34
  241. package/lib/crypto/verification/SASDecimal.js.map +0 -1
  242. package/lib/crypto/verification/request/Channel.d.ts +0 -18
  243. package/lib/crypto/verification/request/Channel.d.ts.map +0 -1
  244. package/lib/crypto/verification/request/Channel.js +0 -1
  245. package/lib/crypto/verification/request/Channel.js.map +0 -1
  246. package/lib/crypto/verification/request/InRoomChannel.d.ts +0 -113
  247. package/lib/crypto/verification/request/InRoomChannel.d.ts.map +0 -1
  248. package/lib/crypto/verification/request/InRoomChannel.js +0 -351
  249. package/lib/crypto/verification/request/InRoomChannel.js.map +0 -1
  250. package/lib/crypto/verification/request/ToDeviceChannel.d.ts +0 -105
  251. package/lib/crypto/verification/request/ToDeviceChannel.d.ts.map +0 -1
  252. package/lib/crypto/verification/request/ToDeviceChannel.js +0 -328
  253. package/lib/crypto/verification/request/ToDeviceChannel.js.map +0 -1
  254. package/lib/crypto/verification/request/VerificationRequest.d.ts +0 -227
  255. package/lib/crypto/verification/request/VerificationRequest.d.ts.map +0 -1
  256. package/lib/crypto/verification/request/VerificationRequest.js +0 -937
  257. package/lib/crypto/verification/request/VerificationRequest.js.map +0 -1
  258. package/lib/crypto-api/CryptoEvent.d.ts +0 -69
  259. package/lib/crypto-api/CryptoEvent.d.ts.map +0 -1
  260. package/lib/crypto-api/CryptoEvent.js +0 -33
  261. package/lib/crypto-api/CryptoEvent.js.map +0 -1
  262. package/lib/crypto-api/CryptoEventHandlerMap.d.ts +0 -16
  263. package/lib/crypto-api/CryptoEventHandlerMap.d.ts.map +0 -1
  264. package/lib/crypto-api/CryptoEventHandlerMap.js +0 -22
  265. package/lib/crypto-api/CryptoEventHandlerMap.js.map +0 -1
  266. package/lib/crypto-api/index.d.ts +0 -978
  267. package/lib/crypto-api/index.d.ts.map +0 -1
  268. package/lib/crypto-api/index.js +0 -304
  269. package/lib/crypto-api/index.js.map +0 -1
  270. package/lib/crypto-api/key-passphrase.d.ts +0 -11
  271. package/lib/crypto-api/key-passphrase.d.ts.map +0 -1
  272. package/lib/crypto-api/key-passphrase.js +0 -51
  273. package/lib/crypto-api/key-passphrase.js.map +0 -1
  274. package/lib/crypto-api/keybackup.d.ts +0 -88
  275. package/lib/crypto-api/keybackup.d.ts.map +0 -1
  276. package/lib/crypto-api/keybackup.js +0 -1
  277. package/lib/crypto-api/keybackup.js.map +0 -1
  278. package/lib/crypto-api/recovery-key.d.ts +0 -11
  279. package/lib/crypto-api/recovery-key.d.ts.map +0 -1
  280. package/lib/crypto-api/recovery-key.js +0 -65
  281. package/lib/crypto-api/recovery-key.js.map +0 -1
  282. package/lib/crypto-api/verification.d.ts +0 -344
  283. package/lib/crypto-api/verification.d.ts.map +0 -1
  284. package/lib/crypto-api/verification.js +0 -91
  285. package/lib/crypto-api/verification.js.map +0 -1
  286. package/lib/rendezvous/MSC4108SignInWithQR.d.ts +0 -112
  287. package/lib/rendezvous/MSC4108SignInWithQR.d.ts.map +0 -1
  288. package/lib/rendezvous/MSC4108SignInWithQR.js +0 -392
  289. package/lib/rendezvous/MSC4108SignInWithQR.js.map +0 -1
  290. package/lib/rendezvous/RendezvousChannel.d.ts +0 -27
  291. package/lib/rendezvous/RendezvousChannel.d.ts.map +0 -1
  292. package/lib/rendezvous/RendezvousChannel.js +0 -1
  293. package/lib/rendezvous/RendezvousChannel.js.map +0 -1
  294. package/lib/rendezvous/RendezvousCode.d.ts +0 -9
  295. package/lib/rendezvous/RendezvousCode.d.ts.map +0 -1
  296. package/lib/rendezvous/RendezvousCode.js +0 -1
  297. package/lib/rendezvous/RendezvousCode.js.map +0 -1
  298. package/lib/rendezvous/RendezvousError.d.ts +0 -6
  299. package/lib/rendezvous/RendezvousError.d.ts.map +0 -1
  300. package/lib/rendezvous/RendezvousError.js +0 -23
  301. package/lib/rendezvous/RendezvousError.js.map +0 -1
  302. package/lib/rendezvous/RendezvousFailureReason.d.ts +0 -31
  303. package/lib/rendezvous/RendezvousFailureReason.d.ts.map +0 -1
  304. package/lib/rendezvous/RendezvousFailureReason.js +0 -38
  305. package/lib/rendezvous/RendezvousFailureReason.js.map +0 -1
  306. package/lib/rendezvous/RendezvousIntent.d.ts +0 -5
  307. package/lib/rendezvous/RendezvousIntent.d.ts.map +0 -1
  308. package/lib/rendezvous/RendezvousIntent.js +0 -22
  309. package/lib/rendezvous/RendezvousIntent.js.map +0 -1
  310. package/lib/rendezvous/RendezvousTransport.d.ts +0 -36
  311. package/lib/rendezvous/RendezvousTransport.d.ts.map +0 -1
  312. package/lib/rendezvous/RendezvousTransport.js +0 -1
  313. package/lib/rendezvous/RendezvousTransport.js.map +0 -1
  314. package/lib/rendezvous/channels/MSC4108SecureChannel.d.ts +0 -58
  315. package/lib/rendezvous/channels/MSC4108SecureChannel.d.ts.map +0 -1
  316. package/lib/rendezvous/channels/MSC4108SecureChannel.js +0 -246
  317. package/lib/rendezvous/channels/MSC4108SecureChannel.js.map +0 -1
  318. package/lib/rendezvous/channels/index.d.ts +0 -2
  319. package/lib/rendezvous/channels/index.d.ts.map +0 -1
  320. package/lib/rendezvous/channels/index.js +0 -18
  321. package/lib/rendezvous/channels/index.js.map +0 -1
  322. package/lib/rendezvous/index.d.ts +0 -10
  323. package/lib/rendezvous/index.d.ts.map +0 -1
  324. package/lib/rendezvous/index.js +0 -23
  325. package/lib/rendezvous/index.js.map +0 -1
  326. package/lib/rendezvous/transports/MSC4108RendezvousSession.d.ts +0 -61
  327. package/lib/rendezvous/transports/MSC4108RendezvousSession.d.ts.map +0 -1
  328. package/lib/rendezvous/transports/MSC4108RendezvousSession.js +0 -253
  329. package/lib/rendezvous/transports/MSC4108RendezvousSession.js.map +0 -1
  330. package/lib/rendezvous/transports/index.d.ts +0 -2
  331. package/lib/rendezvous/transports/index.d.ts.map +0 -1
  332. package/lib/rendezvous/transports/index.js +0 -18
  333. package/lib/rendezvous/transports/index.js.map +0 -1
  334. package/lib/rust-crypto/CrossSigningIdentity.d.ts +0 -33
  335. package/lib/rust-crypto/CrossSigningIdentity.d.ts.map +0 -1
  336. package/lib/rust-crypto/CrossSigningIdentity.js +0 -157
  337. package/lib/rust-crypto/CrossSigningIdentity.js.map +0 -1
  338. package/lib/rust-crypto/DehydratedDeviceManager.d.ts +0 -98
  339. package/lib/rust-crypto/DehydratedDeviceManager.d.ts.map +0 -1
  340. package/lib/rust-crypto/DehydratedDeviceManager.js +0 -285
  341. package/lib/rust-crypto/DehydratedDeviceManager.js.map +0 -1
  342. package/lib/rust-crypto/KeyClaimManager.d.ts +0 -33
  343. package/lib/rust-crypto/KeyClaimManager.d.ts.map +0 -1
  344. package/lib/rust-crypto/KeyClaimManager.js +0 -82
  345. package/lib/rust-crypto/KeyClaimManager.js.map +0 -1
  346. package/lib/rust-crypto/OutgoingRequestProcessor.d.ts +0 -43
  347. package/lib/rust-crypto/OutgoingRequestProcessor.d.ts.map +0 -1
  348. package/lib/rust-crypto/OutgoingRequestProcessor.js +0 -195
  349. package/lib/rust-crypto/OutgoingRequestProcessor.js.map +0 -1
  350. package/lib/rust-crypto/OutgoingRequestsManager.d.ts +0 -47
  351. package/lib/rust-crypto/OutgoingRequestsManager.d.ts.map +0 -1
  352. package/lib/rust-crypto/OutgoingRequestsManager.js +0 -148
  353. package/lib/rust-crypto/OutgoingRequestsManager.js.map +0 -1
  354. package/lib/rust-crypto/PerSessionKeyBackupDownloader.d.ts +0 -120
  355. package/lib/rust-crypto/PerSessionKeyBackupDownloader.d.ts.map +0 -1
  356. package/lib/rust-crypto/PerSessionKeyBackupDownloader.js +0 -467
  357. package/lib/rust-crypto/PerSessionKeyBackupDownloader.js.map +0 -1
  358. package/lib/rust-crypto/RoomEncryptor.d.ts +0 -98
  359. package/lib/rust-crypto/RoomEncryptor.d.ts.map +0 -1
  360. package/lib/rust-crypto/RoomEncryptor.js +0 -299
  361. package/lib/rust-crypto/RoomEncryptor.js.map +0 -1
  362. package/lib/rust-crypto/backup.d.ts +0 -254
  363. package/lib/rust-crypto/backup.d.ts.map +0 -1
  364. package/lib/rust-crypto/backup.js +0 -837
  365. package/lib/rust-crypto/backup.js.map +0 -1
  366. package/lib/rust-crypto/constants.d.ts +0 -3
  367. package/lib/rust-crypto/constants.d.ts.map +0 -1
  368. package/lib/rust-crypto/constants.js +0 -19
  369. package/lib/rust-crypto/constants.js.map +0 -1
  370. package/lib/rust-crypto/device-converter.d.ts +0 -28
  371. package/lib/rust-crypto/device-converter.d.ts.map +0 -1
  372. package/lib/rust-crypto/device-converter.js +0 -123
  373. package/lib/rust-crypto/device-converter.js.map +0 -1
  374. package/lib/rust-crypto/index.d.ts +0 -61
  375. package/lib/rust-crypto/index.d.ts.map +0 -1
  376. package/lib/rust-crypto/index.js +0 -152
  377. package/lib/rust-crypto/index.js.map +0 -1
  378. package/lib/rust-crypto/libolm_migration.d.ts +0 -81
  379. package/lib/rust-crypto/libolm_migration.d.ts.map +0 -1
  380. package/lib/rust-crypto/libolm_migration.js +0 -459
  381. package/lib/rust-crypto/libolm_migration.js.map +0 -1
  382. package/lib/rust-crypto/rust-crypto.d.ts +0 -556
  383. package/lib/rust-crypto/rust-crypto.d.ts.map +0 -1
  384. package/lib/rust-crypto/rust-crypto.js +0 -2016
  385. package/lib/rust-crypto/rust-crypto.js.map +0 -1
  386. package/lib/rust-crypto/secret-storage.d.ts +0 -22
  387. package/lib/rust-crypto/secret-storage.d.ts.map +0 -1
  388. package/lib/rust-crypto/secret-storage.js +0 -63
  389. package/lib/rust-crypto/secret-storage.js.map +0 -1
  390. package/lib/rust-crypto/verification.d.ts +0 -319
  391. package/lib/rust-crypto/verification.d.ts.map +0 -1
  392. package/lib/rust-crypto/verification.js +0 -816
  393. package/lib/rust-crypto/verification.js.map +0 -1
  394. package/lib/secret-storage.d.ts +0 -370
  395. package/lib/secret-storage.d.ts.map +0 -1
  396. package/lib/secret-storage.js +0 -466
  397. package/lib/secret-storage.js.map +0 -1
  398. package/lib/utils/decryptAESSecretStorageItem.d.ts +0 -12
  399. package/lib/utils/decryptAESSecretStorageItem.d.ts.map +0 -1
  400. package/lib/utils/decryptAESSecretStorageItem.js +0 -50
  401. package/lib/utils/decryptAESSecretStorageItem.js.map +0 -1
  402. package/lib/utils/encryptAESSecretStorageItem.d.ts +0 -16
  403. package/lib/utils/encryptAESSecretStorageItem.d.ts.map +0 -1
  404. package/lib/utils/encryptAESSecretStorageItem.js +0 -68
  405. package/lib/utils/encryptAESSecretStorageItem.js.map +0 -1
  406. package/lib/utils/internal/deriveKeys.d.ts +0 -10
  407. package/lib/utils/internal/deriveKeys.d.ts.map +0 -1
  408. package/lib/utils/internal/deriveKeys.js +0 -60
  409. package/lib/utils/internal/deriveKeys.js.map +0 -1
  410. package/src/@types/AESEncryptedSecretStoragePayload.ts +0 -29
  411. package/src/@types/crypto.ts +0 -73
  412. package/src/@types/matrix-sdk-crypto-wasm.d.ts +0 -44
  413. package/src/common-crypto/CryptoBackend.ts +0 -302
  414. package/src/common-crypto/README.md +0 -4
  415. package/src/common-crypto/key-passphrase.ts +0 -43
  416. package/src/crypto/CrossSigning.ts +0 -773
  417. package/src/crypto/DeviceList.ts +0 -989
  418. package/src/crypto/EncryptionSetup.ts +0 -351
  419. package/src/crypto/OlmDevice.ts +0 -1500
  420. package/src/crypto/OutgoingRoomKeyRequestManager.ts +0 -485
  421. package/src/crypto/RoomList.ts +0 -70
  422. package/src/crypto/SecretSharing.ts +0 -240
  423. package/src/crypto/SecretStorage.ts +0 -136
  424. package/src/crypto/aes.ts +0 -23
  425. package/src/crypto/algorithms/base.ts +0 -236
  426. package/src/crypto/algorithms/index.ts +0 -20
  427. package/src/crypto/algorithms/megolm.ts +0 -2216
  428. package/src/crypto/algorithms/olm.ts +0 -381
  429. package/src/crypto/api.ts +0 -70
  430. package/src/crypto/backup.ts +0 -922
  431. package/src/crypto/crypto.ts +0 -18
  432. package/src/crypto/dehydration.ts +0 -272
  433. package/src/crypto/device-converter.ts +0 -45
  434. package/src/crypto/deviceinfo.ts +0 -158
  435. package/src/crypto/index.ts +0 -4414
  436. package/src/crypto/key_passphrase.ts +0 -42
  437. package/src/crypto/keybackup.ts +0 -47
  438. package/src/crypto/olmlib.ts +0 -539
  439. package/src/crypto/recoverykey.ts +0 -18
  440. package/src/crypto/store/base.ts +0 -348
  441. package/src/crypto/store/indexeddb-crypto-store-backend.ts +0 -1250
  442. package/src/crypto/store/indexeddb-crypto-store.ts +0 -845
  443. package/src/crypto/store/localStorage-crypto-store.ts +0 -579
  444. package/src/crypto/store/memory-crypto-store.ts +0 -680
  445. package/src/crypto/verification/Base.ts +0 -409
  446. package/src/crypto/verification/Error.ts +0 -76
  447. package/src/crypto/verification/IllegalMethod.ts +0 -50
  448. package/src/crypto/verification/QRCode.ts +0 -310
  449. package/src/crypto/verification/SAS.ts +0 -494
  450. package/src/crypto/verification/SASDecimal.ts +0 -37
  451. package/src/crypto/verification/request/Channel.ts +0 -34
  452. package/src/crypto/verification/request/InRoomChannel.ts +0 -371
  453. package/src/crypto/verification/request/ToDeviceChannel.ts +0 -354
  454. package/src/crypto/verification/request/VerificationRequest.ts +0 -976
  455. package/src/crypto-api/CryptoEvent.ts +0 -93
  456. package/src/crypto-api/CryptoEventHandlerMap.ts +0 -32
  457. package/src/crypto-api/index.ts +0 -1175
  458. package/src/crypto-api/key-passphrase.ts +0 -58
  459. package/src/crypto-api/keybackup.ts +0 -115
  460. package/src/crypto-api/recovery-key.ts +0 -69
  461. package/src/crypto-api/verification.ts +0 -408
  462. package/src/rendezvous/MSC4108SignInWithQR.ts +0 -444
  463. package/src/rendezvous/RendezvousChannel.ts +0 -48
  464. package/src/rendezvous/RendezvousCode.ts +0 -25
  465. package/src/rendezvous/RendezvousError.ts +0 -26
  466. package/src/rendezvous/RendezvousFailureReason.ts +0 -49
  467. package/src/rendezvous/RendezvousIntent.ts +0 -20
  468. package/src/rendezvous/RendezvousTransport.ts +0 -58
  469. package/src/rendezvous/channels/MSC4108SecureChannel.ts +0 -270
  470. package/src/rendezvous/channels/index.ts +0 -17
  471. package/src/rendezvous/index.ts +0 -25
  472. package/src/rendezvous/transports/MSC4108RendezvousSession.ts +0 -270
  473. package/src/rendezvous/transports/index.ts +0 -17
  474. package/src/rust-crypto/CrossSigningIdentity.ts +0 -183
  475. package/src/rust-crypto/DehydratedDeviceManager.ts +0 -306
  476. package/src/rust-crypto/KeyClaimManager.ts +0 -86
  477. package/src/rust-crypto/OutgoingRequestProcessor.ts +0 -236
  478. package/src/rust-crypto/OutgoingRequestsManager.ts +0 -143
  479. package/src/rust-crypto/PerSessionKeyBackupDownloader.ts +0 -501
  480. package/src/rust-crypto/RoomEncryptor.ts +0 -352
  481. package/src/rust-crypto/backup.ts +0 -881
  482. package/src/rust-crypto/constants.ts +0 -18
  483. package/src/rust-crypto/device-converter.ts +0 -128
  484. package/src/rust-crypto/index.ts +0 -237
  485. package/src/rust-crypto/libolm_migration.ts +0 -530
  486. package/src/rust-crypto/rust-crypto.ts +0 -2205
  487. package/src/rust-crypto/secret-storage.ts +0 -60
  488. package/src/rust-crypto/verification.ts +0 -830
  489. package/src/secret-storage.ts +0 -693
  490. package/src/utils/decryptAESSecretStorageItem.ts +0 -54
  491. package/src/utils/encryptAESSecretStorageItem.ts +0 -73
  492. package/src/utils/internal/deriveKeys.ts +0 -63
@@ -1,2205 +0,0 @@
1
- /*
2
- Copyright 2022-2023 The Matrix.org Foundation C.I.C.
3
-
4
- Licensed under the Apache License, Version 2.0 (the "License");
5
- you may not use this file except in compliance with the License.
6
- You may obtain a copy of the License at
7
-
8
- http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- Unless required by applicable law or agreed to in writing, software
11
- distributed under the License is distributed on an "AS IS" BASIS,
12
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- See the License for the specific language governing permissions and
14
- limitations under the License.
15
- */
16
-
17
- import anotherjson from "another-json";
18
- import * as RustSdkCryptoJs from "@matrix-org/matrix-sdk-crypto-wasm";
19
-
20
- import type { IEventDecryptionResult, IMegolmSessionData } from "../@types/crypto.ts";
21
- import { KnownMembership } from "../@types/membership.ts";
22
- import type { IDeviceLists, IToDeviceEvent } from "../sync-accumulator.ts";
23
- import type { IEncryptedEventInfo } from "../crypto/api.ts";
24
- import type { ToDevicePayload, ToDeviceBatch } from "../models/ToDeviceMessage.ts";
25
- import { MatrixEvent, MatrixEventEvent } from "../models/event.ts";
26
- import { Room } from "../models/room.ts";
27
- import { RoomMember } from "../models/room-member.ts";
28
- import {
29
- BackupDecryptor,
30
- CryptoBackend,
31
- DecryptionError,
32
- OnSyncCompletedData,
33
- } from "../common-crypto/CryptoBackend.ts";
34
- import { logger, Logger, LogSpan } from "../logger.ts";
35
- import { IHttpOpts, MatrixHttpApi, Method } from "../http-api/index.ts";
36
- import { RoomEncryptor } from "./RoomEncryptor.ts";
37
- import { OutgoingRequestProcessor } from "./OutgoingRequestProcessor.ts";
38
- import { KeyClaimManager } from "./KeyClaimManager.ts";
39
- import { logDuration, MapWithDefault } from "../utils.ts";
40
- import {
41
- BackupTrustInfo,
42
- BootstrapCrossSigningOpts,
43
- CreateSecretStorageOpts,
44
- CrossSigningKey,
45
- CrossSigningKeyInfo,
46
- CrossSigningStatus,
47
- CryptoApi,
48
- CryptoCallbacks,
49
- DecryptionFailureCode,
50
- DeviceVerificationStatus,
51
- EventEncryptionInfo,
52
- EventShieldColour,
53
- EventShieldReason,
54
- GeneratedSecretStorageKey,
55
- ImportRoomKeysOpts,
56
- KeyBackupCheck,
57
- KeyBackupInfo,
58
- OwnDeviceKeys,
59
- UserVerificationStatus,
60
- VerificationRequest,
61
- encodeRecoveryKey,
62
- deriveRecoveryKeyFromPassphrase,
63
- DeviceIsolationMode,
64
- AllDevicesIsolationMode,
65
- DeviceIsolationModeKind,
66
- CryptoEvent,
67
- CryptoEventHandlerMap,
68
- KeyBackupRestoreOpts,
69
- KeyBackupRestoreResult,
70
- } from "../crypto-api/index.ts";
71
- import { deviceKeysToDeviceMap, rustDeviceToJsDevice } from "./device-converter.ts";
72
- import { IDownloadKeyResult, IQueryKeysRequest } from "../client.ts";
73
- import { Device, DeviceMap } from "../models/device.ts";
74
- import { SECRET_STORAGE_ALGORITHM_V1_AES, ServerSideSecretStorage } from "../secret-storage.ts";
75
- import { CrossSigningIdentity } from "./CrossSigningIdentity.ts";
76
- import { secretStorageCanAccessSecrets, secretStorageContainsCrossSigningKeys } from "./secret-storage.ts";
77
- import { isVerificationEvent, RustVerificationRequest, verificationMethodIdentifierToMethod } from "./verification.ts";
78
- import { EventType, MsgType } from "../@types/event.ts";
79
- import { TypedEventEmitter } from "../models/typed-event-emitter.ts";
80
- import { decryptionKeyMatchesKeyBackupInfo, RustBackupManager } from "./backup.ts";
81
- import { TypedReEmitter } from "../ReEmitter.ts";
82
- import { randomString } from "../randomstring.ts";
83
- import { ClientStoppedError } from "../errors.ts";
84
- import { ISignatures } from "../@types/signed.ts";
85
- import { decodeBase64, encodeBase64 } from "../base64.ts";
86
- import { OutgoingRequestsManager } from "./OutgoingRequestsManager.ts";
87
- import { PerSessionKeyBackupDownloader } from "./PerSessionKeyBackupDownloader.ts";
88
- import { DehydratedDeviceManager } from "./DehydratedDeviceManager.ts";
89
- import { VerificationMethod } from "../types.ts";
90
- import { keyFromAuthData } from "../common-crypto/key-passphrase.ts";
91
-
92
- const ALL_VERIFICATION_METHODS = [
93
- VerificationMethod.Sas,
94
- VerificationMethod.ScanQrCode,
95
- VerificationMethod.ShowQrCode,
96
- VerificationMethod.Reciprocate,
97
- ];
98
-
99
- interface ISignableObject {
100
- signatures?: ISignatures;
101
- unsigned?: object;
102
- }
103
-
104
- /**
105
- * An implementation of {@link CryptoBackend} using the Rust matrix-sdk-crypto.
106
- *
107
- * @internal
108
- */
109
- export class RustCrypto extends TypedEventEmitter<RustCryptoEvents, CryptoEventHandlerMap> implements CryptoBackend {
110
- /**
111
- * The number of iterations to use when deriving a recovery key from a passphrase.
112
- */
113
- private readonly RECOVERY_KEY_DERIVATION_ITERATIONS = 500000;
114
-
115
- private _trustCrossSignedDevices = true;
116
- private deviceIsolationMode: DeviceIsolationMode = new AllDevicesIsolationMode(false);
117
-
118
- /** whether {@link stop} has been called */
119
- private stopped = false;
120
-
121
- /** mapping of roomId → encryptor class */
122
- private roomEncryptors: Record<string, RoomEncryptor> = {};
123
-
124
- private eventDecryptor: EventDecryptor;
125
- private keyClaimManager: KeyClaimManager;
126
- private outgoingRequestProcessor: OutgoingRequestProcessor;
127
- private crossSigningIdentity: CrossSigningIdentity;
128
- private readonly backupManager: RustBackupManager;
129
- private outgoingRequestsManager: OutgoingRequestsManager;
130
- private readonly perSessionBackupDownloader: PerSessionKeyBackupDownloader;
131
- private readonly dehydratedDeviceManager: DehydratedDeviceManager;
132
- private readonly reemitter = new TypedReEmitter<RustCryptoEvents, CryptoEventHandlerMap>(this);
133
-
134
- public constructor(
135
- private readonly logger: Logger,
136
-
137
- /** The `OlmMachine` from the underlying rust crypto sdk. */
138
- private readonly olmMachine: RustSdkCryptoJs.OlmMachine,
139
-
140
- /**
141
- * Low-level HTTP interface: used to make outgoing requests required by the rust SDK.
142
- *
143
- * We expect it to set the access token, etc.
144
- */
145
- private readonly http: MatrixHttpApi<IHttpOpts & { onlyData: true }>,
146
-
147
- /** The local user's User ID. */
148
- private readonly userId: string,
149
-
150
- /** The local user's Device ID. */
151
- _deviceId: string,
152
-
153
- /** Interface to server-side secret storage */
154
- private readonly secretStorage: ServerSideSecretStorage,
155
-
156
- /** Crypto callbacks provided by the application */
157
- private readonly cryptoCallbacks: CryptoCallbacks,
158
- ) {
159
- super();
160
- this.outgoingRequestProcessor = new OutgoingRequestProcessor(olmMachine, http);
161
- this.outgoingRequestsManager = new OutgoingRequestsManager(
162
- this.logger,
163
- olmMachine,
164
- this.outgoingRequestProcessor,
165
- );
166
-
167
- this.keyClaimManager = new KeyClaimManager(olmMachine, this.outgoingRequestProcessor);
168
-
169
- this.backupManager = new RustBackupManager(olmMachine, http, this.outgoingRequestProcessor);
170
- this.perSessionBackupDownloader = new PerSessionKeyBackupDownloader(
171
- this.logger,
172
- this.olmMachine,
173
- this.http,
174
- this.backupManager,
175
- );
176
- this.dehydratedDeviceManager = new DehydratedDeviceManager(
177
- this.logger,
178
- olmMachine,
179
- http,
180
- this.outgoingRequestProcessor,
181
- secretStorage,
182
- );
183
- this.eventDecryptor = new EventDecryptor(this.logger, olmMachine, this.perSessionBackupDownloader);
184
-
185
- this.reemitter.reEmit(this.backupManager, [
186
- CryptoEvent.KeyBackupStatus,
187
- CryptoEvent.KeyBackupSessionsRemaining,
188
- CryptoEvent.KeyBackupFailed,
189
- CryptoEvent.KeyBackupDecryptionKeyCached,
190
- ]);
191
-
192
- this.crossSigningIdentity = new CrossSigningIdentity(olmMachine, this.outgoingRequestProcessor, secretStorage);
193
-
194
- // Check and start in background the key backup connection
195
- this.checkKeyBackupAndEnable();
196
- }
197
-
198
- /**
199
- * Return the OlmMachine only if {@link RustCrypto#stop} has not been called.
200
- *
201
- * This allows us to better handle race conditions where the client is stopped before or during a crypto API call.
202
- *
203
- * @throws ClientStoppedError if {@link RustCrypto#stop} has been called.
204
- */
205
- private getOlmMachineOrThrow(): RustSdkCryptoJs.OlmMachine {
206
- if (this.stopped) {
207
- throw new ClientStoppedError();
208
- }
209
- return this.olmMachine;
210
- }
211
-
212
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
213
- //
214
- // CryptoBackend implementation
215
- //
216
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
217
-
218
- public set globalErrorOnUnknownDevices(_v: boolean) {
219
- // Not implemented for rust crypto.
220
- }
221
-
222
- public get globalErrorOnUnknownDevices(): boolean {
223
- // Not implemented for rust crypto.
224
- return false;
225
- }
226
-
227
- public stop(): void {
228
- // stop() may be called multiple times, but attempting to close() the OlmMachine twice
229
- // will cause an error.
230
- if (this.stopped) {
231
- return;
232
- }
233
- this.stopped = true;
234
-
235
- this.keyClaimManager.stop();
236
- this.backupManager.stop();
237
- this.outgoingRequestsManager.stop();
238
- this.perSessionBackupDownloader.stop();
239
- this.dehydratedDeviceManager.stop();
240
-
241
- // make sure we close() the OlmMachine; doing so means that all the Rust objects will be
242
- // cleaned up; in particular, the indexeddb connections will be closed, which means they
243
- // can then be deleted.
244
- this.olmMachine.close();
245
- }
246
-
247
- public async encryptEvent(event: MatrixEvent, _room: Room): Promise<void> {
248
- const roomId = event.getRoomId()!;
249
- const encryptor = this.roomEncryptors[roomId];
250
-
251
- if (!encryptor) {
252
- throw new Error(`Cannot encrypt event in unconfigured room ${roomId}`);
253
- }
254
-
255
- await encryptor.encryptEvent(event, this.globalBlacklistUnverifiedDevices, this.deviceIsolationMode);
256
- }
257
-
258
- public async decryptEvent(event: MatrixEvent): Promise<IEventDecryptionResult> {
259
- const roomId = event.getRoomId();
260
- if (!roomId) {
261
- // presumably, a to-device message. These are normally decrypted in preprocessToDeviceMessages
262
- // so the fact it has come back here suggests that decryption failed.
263
- //
264
- // once we drop support for the libolm crypto implementation, we can stop passing to-device messages
265
- // through decryptEvent and hence get rid of this case.
266
- throw new Error("to-device event was not decrypted in preprocessToDeviceMessages");
267
- }
268
- return await this.eventDecryptor.attemptEventDecryption(event, this.deviceIsolationMode);
269
- }
270
-
271
- /**
272
- * Implementation of (deprecated) {@link MatrixClient#getEventEncryptionInfo}.
273
- *
274
- * @param event - event to inspect
275
- */
276
- public getEventEncryptionInfo(event: MatrixEvent): IEncryptedEventInfo {
277
- const ret: Partial<IEncryptedEventInfo> = {};
278
-
279
- ret.senderKey = event.getSenderKey() ?? undefined;
280
- ret.algorithm = event.getWireContent().algorithm;
281
-
282
- if (!ret.senderKey || !ret.algorithm) {
283
- ret.encrypted = false;
284
- return ret as IEncryptedEventInfo;
285
- }
286
- ret.encrypted = true;
287
- ret.authenticated = true;
288
- ret.mismatchedSender = true;
289
- return ret as IEncryptedEventInfo;
290
- }
291
-
292
- /**
293
- * Implementation of {@link CryptoBackend#checkUserTrust}.
294
- *
295
- * Stub for backwards compatibility.
296
- *
297
- */
298
- public checkUserTrust(userId: string): UserVerificationStatus {
299
- return new UserVerificationStatus(false, false, false);
300
- }
301
-
302
- /**
303
- * Get the cross signing information for a given user.
304
- *
305
- * The cross-signing API is currently UNSTABLE and may change without notice.
306
- *
307
- * @param userId - the user ID to get the cross-signing info for.
308
- *
309
- * @returns the cross signing information for the user.
310
- */
311
- public getStoredCrossSigningForUser(userId: string): null {
312
- // TODO
313
- return null;
314
- }
315
-
316
- /**
317
- * This function is unneeded for the rust-crypto.
318
- * The cross signing key import and the device verification are done in {@link CryptoApi#bootstrapCrossSigning}
319
- *
320
- * The function is stub to keep the compatibility with the old crypto.
321
- * More information: https://github.com/vector-im/element-web/issues/25648
322
- *
323
- * Implementation of {@link CryptoBackend#checkOwnCrossSigningTrust}
324
- */
325
- public async checkOwnCrossSigningTrust(): Promise<void> {
326
- return;
327
- }
328
-
329
- /**
330
- * Implementation of {@link CryptoBackend#getBackupDecryptor}.
331
- */
332
- public async getBackupDecryptor(backupInfo: KeyBackupInfo, privKey: ArrayLike<number>): Promise<BackupDecryptor> {
333
- if (!(privKey instanceof Uint8Array)) {
334
- throw new Error(`getBackupDecryptor: expects Uint8Array`);
335
- }
336
-
337
- if (backupInfo.algorithm != "m.megolm_backup.v1.curve25519-aes-sha2") {
338
- throw new Error(`getBackupDecryptor: Unsupported algorithm ${backupInfo.algorithm}`);
339
- }
340
-
341
- const backupDecryptionKey = RustSdkCryptoJs.BackupDecryptionKey.fromBase64(encodeBase64(privKey));
342
- if (!decryptionKeyMatchesKeyBackupInfo(backupDecryptionKey, backupInfo)) {
343
- throw new Error(`getBackupDecryptor: key backup on server does not match the decryption key`);
344
- }
345
-
346
- return this.backupManager.createBackupDecryptor(backupDecryptionKey);
347
- }
348
-
349
- /**
350
- * Implementation of {@link CryptoBackend#importBackedUpRoomKeys}.
351
- */
352
- public async importBackedUpRoomKeys(
353
- keys: IMegolmSessionData[],
354
- backupVersion: string,
355
- opts?: ImportRoomKeysOpts,
356
- ): Promise<void> {
357
- return await this.backupManager.importBackedUpRoomKeys(keys, backupVersion, opts);
358
- }
359
-
360
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
361
- //
362
- // CryptoApi implementation
363
- //
364
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
365
-
366
- public globalBlacklistUnverifiedDevices = false;
367
-
368
- /**
369
- * Implementation of {@link CryptoApi#getVersion}.
370
- */
371
- public getVersion(): string {
372
- const versions = RustSdkCryptoJs.getVersions();
373
- return `Rust SDK ${versions.matrix_sdk_crypto} (${versions.git_sha}), Vodozemac ${versions.vodozemac}`;
374
- }
375
-
376
- /**
377
- * Implementation of {@link CryptoApi#setDeviceIsolationMode}.
378
- */
379
- public setDeviceIsolationMode(isolationMode: DeviceIsolationMode): void {
380
- this.deviceIsolationMode = isolationMode;
381
- }
382
-
383
- /**
384
- * Implementation of {@link CryptoApi#isEncryptionEnabledInRoom}.
385
- */
386
- public async isEncryptionEnabledInRoom(roomId: string): Promise<boolean> {
387
- const roomSettings: RustSdkCryptoJs.RoomSettings | undefined = await this.olmMachine.getRoomSettings(
388
- new RustSdkCryptoJs.RoomId(roomId),
389
- );
390
- return Boolean(roomSettings?.algorithm);
391
- }
392
-
393
- /**
394
- * Implementation of {@link CryptoApi#getOwnDeviceKeys}.
395
- */
396
- public async getOwnDeviceKeys(): Promise<OwnDeviceKeys> {
397
- const keys = this.olmMachine.identityKeys;
398
- return { ed25519: keys.ed25519.toBase64(), curve25519: keys.curve25519.toBase64() };
399
- }
400
-
401
- public prepareToEncrypt(room: Room): void {
402
- const encryptor = this.roomEncryptors[room.roomId];
403
-
404
- if (encryptor) {
405
- encryptor.prepareForEncryption(this.globalBlacklistUnverifiedDevices, this.deviceIsolationMode);
406
- }
407
- }
408
-
409
- public forceDiscardSession(roomId: string): Promise<void> {
410
- return this.roomEncryptors[roomId]?.forceDiscardSession();
411
- }
412
-
413
- public async exportRoomKeys(): Promise<IMegolmSessionData[]> {
414
- const raw = await this.olmMachine.exportRoomKeys(() => true);
415
- return JSON.parse(raw);
416
- }
417
-
418
- public async exportRoomKeysAsJson(): Promise<string> {
419
- return await this.olmMachine.exportRoomKeys(() => true);
420
- }
421
-
422
- public async importRoomKeys(keys: IMegolmSessionData[], opts?: ImportRoomKeysOpts): Promise<void> {
423
- return await this.backupManager.importRoomKeys(keys, opts);
424
- }
425
-
426
- public async importRoomKeysAsJson(keys: string, opts?: ImportRoomKeysOpts): Promise<void> {
427
- return await this.backupManager.importRoomKeysAsJson(keys, opts);
428
- }
429
-
430
- /**
431
- * Implementation of {@link CryptoApi.userHasCrossSigningKeys}.
432
- */
433
- public async userHasCrossSigningKeys(userId = this.userId, downloadUncached = false): Promise<boolean> {
434
- // TODO: could probably do with a more efficient way of doing this than returning the whole set and searching
435
- const rustTrackedUsers: Set<RustSdkCryptoJs.UserId> = await this.olmMachine.trackedUsers();
436
- let rustTrackedUser: RustSdkCryptoJs.UserId | undefined;
437
- for (const u of rustTrackedUsers) {
438
- if (userId === u.toString()) {
439
- rustTrackedUser = u;
440
- break;
441
- }
442
- }
443
-
444
- if (rustTrackedUser !== undefined) {
445
- if (userId === this.userId) {
446
- /* make sure we have an *up-to-date* idea of the user's cross-signing keys. This is important, because if we
447
- * return "false" here, we will end up generating new cross-signing keys and replacing the existing ones.
448
- */
449
- const request = this.olmMachine.queryKeysForUsers(
450
- // clone as rust layer will take ownership and it's reused later
451
- [rustTrackedUser.clone()],
452
- );
453
- await this.outgoingRequestProcessor.makeOutgoingRequest(request);
454
- }
455
- const userIdentity = await this.olmMachine.getIdentity(rustTrackedUser);
456
- userIdentity?.free();
457
- return userIdentity !== undefined;
458
- } else if (downloadUncached) {
459
- // Download the cross signing keys and check if the master key is available
460
- const keyResult = await this.downloadDeviceList(new Set([userId]));
461
- const keys = keyResult.master_keys?.[userId];
462
-
463
- // No master key
464
- if (!keys) return false;
465
-
466
- // `keys` is an object with { [`ed25519:${pubKey}`]: pubKey }
467
- // We assume only a single key, and we want the bare form without type
468
- // prefix, so we select the values.
469
- return Boolean(Object.values(keys.keys)[0]);
470
- } else {
471
- return false;
472
- }
473
- }
474
-
475
- /**
476
- * Get the device information for the given list of users.
477
- *
478
- * @param userIds - The users to fetch.
479
- * @param downloadUncached - If true, download the device list for users whose device list we are not
480
- * currently tracking. Defaults to false, in which case such users will not appear at all in the result map.
481
- *
482
- * @returns A map `{@link DeviceMap}`.
483
- */
484
- public async getUserDeviceInfo(userIds: string[], downloadUncached = false): Promise<DeviceMap> {
485
- const deviceMapByUserId = new Map<string, Map<string, Device>>();
486
- const rustTrackedUsers: Set<RustSdkCryptoJs.UserId> = await this.getOlmMachineOrThrow().trackedUsers();
487
-
488
- // Convert RustSdkCryptoJs.UserId to a `Set<string>`
489
- const trackedUsers = new Set<string>();
490
- rustTrackedUsers.forEach((rustUserId) => trackedUsers.add(rustUserId.toString()));
491
-
492
- // Keep untracked user to download their keys after
493
- const untrackedUsers: Set<string> = new Set();
494
-
495
- for (const userId of userIds) {
496
- // if this is a tracked user, we can just fetch the device list from the rust-sdk
497
- // (NB: this is probably ok even if we race with a leave event such that we stop tracking the user's
498
- // devices: the rust-sdk will return the last-known device list, which will be good enough.)
499
- if (trackedUsers.has(userId)) {
500
- deviceMapByUserId.set(userId, await this.getUserDevices(userId));
501
- } else {
502
- untrackedUsers.add(userId);
503
- }
504
- }
505
-
506
- // for any users whose device lists we are not tracking, fall back to downloading the device list
507
- // over HTTP.
508
- if (downloadUncached && untrackedUsers.size >= 1) {
509
- const queryResult = await this.downloadDeviceList(untrackedUsers);
510
- Object.entries(queryResult.device_keys).forEach(([userId, deviceKeys]) =>
511
- deviceMapByUserId.set(userId, deviceKeysToDeviceMap(deviceKeys)),
512
- );
513
- }
514
-
515
- return deviceMapByUserId;
516
- }
517
-
518
- /**
519
- * Get the device list for the given user from the olm machine
520
- * @param userId - Rust SDK UserId
521
- */
522
- private async getUserDevices(userId: string): Promise<Map<string, Device>> {
523
- const rustUserId = new RustSdkCryptoJs.UserId(userId);
524
-
525
- // For reasons I don't really understand, the Javascript FinalizationRegistry doesn't seem to run the
526
- // registered callbacks when `userDevices` goes out of scope, nor when the individual devices in the array
527
- // returned by `userDevices.devices` do so.
528
- //
529
- // This is particularly problematic, because each of those structures holds a reference to the
530
- // VerificationMachine, which in turn holds a reference to the IndexeddbCryptoStore. Hence, we end up leaking
531
- // open connections to the crypto store, which means the store can't be deleted on logout.
532
- //
533
- // To fix this, we explicitly call `.free` on each of the objects, which tells the rust code to drop the
534
- // allocated memory and decrement the refcounts for the crypto store.
535
-
536
- // Wait for up to a second for any in-flight device list requests to complete.
537
- // The reason for this isn't so much to avoid races (some level of raciness is
538
- // inevitable for this method) but to make testing easier.
539
- const userDevices: RustSdkCryptoJs.UserDevices = await this.olmMachine.getUserDevices(rustUserId, 1);
540
- try {
541
- const deviceArray: RustSdkCryptoJs.Device[] = userDevices.devices();
542
- try {
543
- return new Map(
544
- deviceArray.map((device) => [device.deviceId.toString(), rustDeviceToJsDevice(device, rustUserId)]),
545
- );
546
- } finally {
547
- deviceArray.forEach((d) => d.free());
548
- }
549
- } finally {
550
- userDevices.free();
551
- }
552
- }
553
-
554
- /**
555
- * Download the given user keys by calling `/keys/query` request
556
- * @param untrackedUsers - download keys of these users
557
- */
558
- private async downloadDeviceList(untrackedUsers: Set<string>): Promise<IDownloadKeyResult> {
559
- const queryBody: IQueryKeysRequest = { device_keys: {} };
560
- untrackedUsers.forEach((user) => (queryBody.device_keys[user] = []));
561
-
562
- return await this.http.authedRequest(Method.Post, "/_matrix/client/v3/keys/query", undefined, queryBody, {
563
- prefix: "",
564
- });
565
- }
566
-
567
- /**
568
- * Implementation of {@link CryptoApi#getTrustCrossSignedDevices}.
569
- */
570
- public getTrustCrossSignedDevices(): boolean {
571
- return this._trustCrossSignedDevices;
572
- }
573
-
574
- /**
575
- * Implementation of {@link CryptoApi#setTrustCrossSignedDevices}.
576
- */
577
- public setTrustCrossSignedDevices(val: boolean): void {
578
- this._trustCrossSignedDevices = val;
579
- // TODO: legacy crypto goes through the list of known devices and emits DeviceVerificationChanged
580
- // events. Maybe we need to do the same?
581
- }
582
-
583
- /**
584
- * Mark the given device as locally verified.
585
- *
586
- * Implementation of {@link CryptoApi#setDeviceVerified}.
587
- */
588
- public async setDeviceVerified(userId: string, deviceId: string, verified = true): Promise<void> {
589
- const device: RustSdkCryptoJs.Device | undefined = await this.olmMachine.getDevice(
590
- new RustSdkCryptoJs.UserId(userId),
591
- new RustSdkCryptoJs.DeviceId(deviceId),
592
- );
593
-
594
- if (!device) {
595
- throw new Error(`Unknown device ${userId}|${deviceId}`);
596
- }
597
- try {
598
- await device.setLocalTrust(
599
- verified ? RustSdkCryptoJs.LocalTrust.Verified : RustSdkCryptoJs.LocalTrust.Unset,
600
- );
601
- } finally {
602
- device.free();
603
- }
604
- }
605
-
606
- /**
607
- * Blindly cross-sign one of our other devices.
608
- *
609
- * Implementation of {@link CryptoApi#crossSignDevice}.
610
- */
611
- public async crossSignDevice(deviceId: string): Promise<void> {
612
- const device: RustSdkCryptoJs.Device | undefined = await this.olmMachine.getDevice(
613
- new RustSdkCryptoJs.UserId(this.userId),
614
- new RustSdkCryptoJs.DeviceId(deviceId),
615
- );
616
- if (!device) {
617
- throw new Error(`Unknown device ${deviceId}`);
618
- }
619
- try {
620
- const outgoingRequest: RustSdkCryptoJs.SignatureUploadRequest = await device.verify();
621
- await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest);
622
- } finally {
623
- device.free();
624
- }
625
- }
626
-
627
- /**
628
- * Implementation of {@link CryptoApi#getDeviceVerificationStatus}.
629
- */
630
- public async getDeviceVerificationStatus(
631
- userId: string,
632
- deviceId: string,
633
- ): Promise<DeviceVerificationStatus | null> {
634
- const device: RustSdkCryptoJs.Device | undefined = await this.olmMachine.getDevice(
635
- new RustSdkCryptoJs.UserId(userId),
636
- new RustSdkCryptoJs.DeviceId(deviceId),
637
- );
638
-
639
- if (!device) return null;
640
- try {
641
- return new DeviceVerificationStatus({
642
- signedByOwner: device.isCrossSignedByOwner(),
643
- crossSigningVerified: device.isCrossSigningTrusted(),
644
- localVerified: device.isLocallyTrusted(),
645
- trustCrossSignedDevices: this._trustCrossSignedDevices,
646
- });
647
- } finally {
648
- device.free();
649
- }
650
- }
651
-
652
- /**
653
- * Implementation of {@link CryptoApi#getUserVerificationStatus}.
654
- */
655
- public async getUserVerificationStatus(userId: string): Promise<UserVerificationStatus> {
656
- const userIdentity: RustSdkCryptoJs.UserIdentity | RustSdkCryptoJs.OwnUserIdentity | undefined =
657
- await this.getOlmMachineOrThrow().getIdentity(new RustSdkCryptoJs.UserId(userId));
658
- if (userIdentity === undefined) {
659
- return new UserVerificationStatus(false, false, false);
660
- }
661
-
662
- const verified = userIdentity.isVerified();
663
- const wasVerified = userIdentity.wasPreviouslyVerified();
664
- const needsUserApproval =
665
- userIdentity instanceof RustSdkCryptoJs.UserIdentity ? userIdentity.identityNeedsUserApproval() : false;
666
- userIdentity.free();
667
- return new UserVerificationStatus(verified, wasVerified, false, needsUserApproval);
668
- }
669
-
670
- /**
671
- * Implementation of {@link CryptoApi#pinCurrentUserIdentity}.
672
- */
673
- public async pinCurrentUserIdentity(userId: string): Promise<void> {
674
- const userIdentity: RustSdkCryptoJs.UserIdentity | RustSdkCryptoJs.OwnUserIdentity | undefined =
675
- await this.getOlmMachineOrThrow().getIdentity(new RustSdkCryptoJs.UserId(userId));
676
-
677
- if (userIdentity === undefined) {
678
- throw new Error("Cannot pin identity of unknown user");
679
- }
680
-
681
- if (userIdentity instanceof RustSdkCryptoJs.OwnUserIdentity) {
682
- throw new Error("Cannot pin identity of own user");
683
- }
684
-
685
- await userIdentity.pinCurrentMasterKey();
686
- }
687
-
688
- /**
689
- * Implementation of {@link CryptoApi#isCrossSigningReady}
690
- */
691
- public async isCrossSigningReady(): Promise<boolean> {
692
- const { privateKeysInSecretStorage, privateKeysCachedLocally } = await this.getCrossSigningStatus();
693
- const hasKeysInCache =
694
- Boolean(privateKeysCachedLocally.masterKey) &&
695
- Boolean(privateKeysCachedLocally.selfSigningKey) &&
696
- Boolean(privateKeysCachedLocally.userSigningKey);
697
-
698
- const identity = await this.getOwnIdentity();
699
-
700
- // Cross-signing is ready if the public identity is trusted, and the private keys
701
- // are either cached, or accessible via secret-storage.
702
- return !!identity?.isVerified() && (hasKeysInCache || privateKeysInSecretStorage);
703
- }
704
-
705
- /**
706
- * Implementation of {@link CryptoApi#getCrossSigningKeyId}
707
- */
708
- public async getCrossSigningKeyId(type: CrossSigningKey = CrossSigningKey.Master): Promise<string | null> {
709
- const userIdentity: RustSdkCryptoJs.OwnUserIdentity | undefined = await this.olmMachine.getIdentity(
710
- new RustSdkCryptoJs.UserId(this.userId),
711
- );
712
- if (!userIdentity) {
713
- // The public keys are not available on this device
714
- return null;
715
- }
716
-
717
- try {
718
- const crossSigningStatus: RustSdkCryptoJs.CrossSigningStatus = await this.olmMachine.crossSigningStatus();
719
-
720
- const privateKeysOnDevice =
721
- crossSigningStatus.hasMaster && crossSigningStatus.hasUserSigning && crossSigningStatus.hasSelfSigning;
722
-
723
- if (!privateKeysOnDevice) {
724
- // The private keys are not available on this device
725
- return null;
726
- }
727
-
728
- if (!userIdentity.isVerified()) {
729
- // We have both public and private keys, but they don't match!
730
- return null;
731
- }
732
-
733
- let key: string;
734
- switch (type) {
735
- case CrossSigningKey.Master:
736
- key = userIdentity.masterKey;
737
- break;
738
- case CrossSigningKey.SelfSigning:
739
- key = userIdentity.selfSigningKey;
740
- break;
741
- case CrossSigningKey.UserSigning:
742
- key = userIdentity.userSigningKey;
743
- break;
744
- default:
745
- // Unknown type
746
- return null;
747
- }
748
-
749
- const parsedKey: CrossSigningKeyInfo = JSON.parse(key);
750
- // `keys` is an object with { [`ed25519:${pubKey}`]: pubKey }
751
- // We assume only a single key, and we want the bare form without type
752
- // prefix, so we select the values.
753
- return Object.values(parsedKey.keys)[0];
754
- } finally {
755
- userIdentity.free();
756
- }
757
- }
758
-
759
- /**
760
- * Implementation of {@link CryptoApi#bootstrapCrossSigning}
761
- */
762
- public async bootstrapCrossSigning(opts: BootstrapCrossSigningOpts): Promise<void> {
763
- await this.crossSigningIdentity.bootstrapCrossSigning(opts);
764
- }
765
-
766
- /**
767
- * Implementation of {@link CryptoApi#isSecretStorageReady}
768
- */
769
- public async isSecretStorageReady(): Promise<boolean> {
770
- // make sure that the cross-signing keys are stored
771
- const secretsToCheck = [
772
- "m.cross_signing.master",
773
- "m.cross_signing.user_signing",
774
- "m.cross_signing.self_signing",
775
- ];
776
-
777
- // if key backup is active, we also need to check that the backup decryption key is stored
778
- const keyBackupEnabled = (await this.backupManager.getActiveBackupVersion()) != null;
779
- if (keyBackupEnabled) {
780
- secretsToCheck.push("m.megolm_backup.v1");
781
- }
782
-
783
- return secretStorageCanAccessSecrets(this.secretStorage, secretsToCheck);
784
- }
785
-
786
- /**
787
- * Implementation of {@link CryptoApi#bootstrapSecretStorage}
788
- */
789
- public async bootstrapSecretStorage({
790
- createSecretStorageKey,
791
- setupNewSecretStorage,
792
- setupNewKeyBackup,
793
- }: CreateSecretStorageOpts = {}): Promise<void> {
794
- // If an AES Key is already stored in the secret storage and setupNewSecretStorage is not set
795
- // we don't want to create a new key
796
- const isNewSecretStorageKeyNeeded = setupNewSecretStorage || !(await this.secretStorageHasAESKey());
797
-
798
- if (isNewSecretStorageKeyNeeded) {
799
- if (!createSecretStorageKey) {
800
- throw new Error("unable to create a new secret storage key, createSecretStorageKey is not set");
801
- }
802
-
803
- // Create a new storage key and add it to secret storage
804
- this.logger.info("bootstrapSecretStorage: creating new secret storage key");
805
- const recoveryKey = await createSecretStorageKey();
806
- if (!recoveryKey) {
807
- throw new Error("createSecretStorageKey() callback did not return a secret storage key");
808
- }
809
- await this.addSecretStorageKeyToSecretStorage(recoveryKey);
810
- }
811
-
812
- const crossSigningStatus: RustSdkCryptoJs.CrossSigningStatus = await this.olmMachine.crossSigningStatus();
813
- const hasPrivateKeys =
814
- crossSigningStatus.hasMaster && crossSigningStatus.hasSelfSigning && crossSigningStatus.hasUserSigning;
815
-
816
- // If we have cross-signing private keys cached, store them in secret
817
- // storage if they are not there already.
818
- if (
819
- hasPrivateKeys &&
820
- (isNewSecretStorageKeyNeeded || !(await secretStorageContainsCrossSigningKeys(this.secretStorage)))
821
- ) {
822
- this.logger.info("bootstrapSecretStorage: cross-signing keys not yet exported; doing so now.");
823
-
824
- const crossSigningPrivateKeys: RustSdkCryptoJs.CrossSigningKeyExport =
825
- await this.olmMachine.exportCrossSigningKeys();
826
-
827
- if (!crossSigningPrivateKeys.masterKey) {
828
- throw new Error("missing master key in cross signing private keys");
829
- }
830
-
831
- if (!crossSigningPrivateKeys.userSigningKey) {
832
- throw new Error("missing user signing key in cross signing private keys");
833
- }
834
-
835
- if (!crossSigningPrivateKeys.self_signing_key) {
836
- throw new Error("missing self signing key in cross signing private keys");
837
- }
838
-
839
- await this.secretStorage.store("m.cross_signing.master", crossSigningPrivateKeys.masterKey);
840
- await this.secretStorage.store("m.cross_signing.user_signing", crossSigningPrivateKeys.userSigningKey);
841
- await this.secretStorage.store("m.cross_signing.self_signing", crossSigningPrivateKeys.self_signing_key);
842
- }
843
-
844
- if (setupNewKeyBackup) {
845
- await this.resetKeyBackup();
846
- }
847
- }
848
-
849
- /**
850
- * Add the secretStorage key to the secret storage
851
- * - The secret storage key must have the `keyInfo` field filled
852
- * - The secret storage key is set as the default key of the secret storage
853
- * - Call `cryptoCallbacks.cacheSecretStorageKey` when done
854
- *
855
- * @param secretStorageKey - The secret storage key to add in the secret storage.
856
- */
857
- private async addSecretStorageKeyToSecretStorage(secretStorageKey: GeneratedSecretStorageKey): Promise<void> {
858
- const secretStorageKeyObject = await this.secretStorage.addKey(SECRET_STORAGE_ALGORITHM_V1_AES, {
859
- passphrase: secretStorageKey.keyInfo?.passphrase,
860
- name: secretStorageKey.keyInfo?.name,
861
- key: secretStorageKey.privateKey,
862
- });
863
-
864
- await this.secretStorage.setDefaultKeyId(secretStorageKeyObject.keyId);
865
-
866
- this.cryptoCallbacks.cacheSecretStorageKey?.(
867
- secretStorageKeyObject.keyId,
868
- secretStorageKeyObject.keyInfo,
869
- secretStorageKey.privateKey,
870
- );
871
- }
872
-
873
- /**
874
- * Check if a secret storage AES Key is already added in secret storage
875
- *
876
- * @returns True if an AES key is in the secret storage
877
- */
878
- private async secretStorageHasAESKey(): Promise<boolean> {
879
- // See if we already have an AES secret-storage key.
880
- const secretStorageKeyTuple = await this.secretStorage.getKey();
881
-
882
- if (!secretStorageKeyTuple) return false;
883
-
884
- const [, keyInfo] = secretStorageKeyTuple;
885
-
886
- // Check if the key is an AES key
887
- return keyInfo.algorithm === SECRET_STORAGE_ALGORITHM_V1_AES;
888
- }
889
-
890
- /**
891
- * Implementation of {@link CryptoApi#getCrossSigningStatus}
892
- */
893
- public async getCrossSigningStatus(): Promise<CrossSigningStatus> {
894
- const userIdentity: RustSdkCryptoJs.OwnUserIdentity | null = await this.getOlmMachineOrThrow().getIdentity(
895
- new RustSdkCryptoJs.UserId(this.userId),
896
- );
897
-
898
- const publicKeysOnDevice =
899
- Boolean(userIdentity?.masterKey) &&
900
- Boolean(userIdentity?.selfSigningKey) &&
901
- Boolean(userIdentity?.userSigningKey);
902
- userIdentity?.free();
903
-
904
- const privateKeysInSecretStorage = await secretStorageContainsCrossSigningKeys(this.secretStorage);
905
- const crossSigningStatus: RustSdkCryptoJs.CrossSigningStatus | null =
906
- await this.getOlmMachineOrThrow().crossSigningStatus();
907
-
908
- return {
909
- publicKeysOnDevice,
910
- privateKeysInSecretStorage,
911
- privateKeysCachedLocally: {
912
- masterKey: Boolean(crossSigningStatus?.hasMaster),
913
- userSigningKey: Boolean(crossSigningStatus?.hasUserSigning),
914
- selfSigningKey: Boolean(crossSigningStatus?.hasSelfSigning),
915
- },
916
- };
917
- }
918
-
919
- /**
920
- * Implementation of {@link CryptoApi#createRecoveryKeyFromPassphrase}
921
- */
922
- public async createRecoveryKeyFromPassphrase(password?: string): Promise<GeneratedSecretStorageKey> {
923
- if (password) {
924
- // Generate the key from the passphrase
925
- // first we generate a random salt
926
- const salt = randomString(32);
927
- // then we derive the key from the passphrase
928
- const recoveryKey = await deriveRecoveryKeyFromPassphrase(
929
- password,
930
- salt,
931
- this.RECOVERY_KEY_DERIVATION_ITERATIONS,
932
- );
933
- return {
934
- keyInfo: {
935
- passphrase: {
936
- algorithm: "m.pbkdf2",
937
- iterations: this.RECOVERY_KEY_DERIVATION_ITERATIONS,
938
- salt,
939
- },
940
- },
941
- privateKey: recoveryKey,
942
- encodedPrivateKey: encodeRecoveryKey(recoveryKey),
943
- };
944
- } else {
945
- // Using the navigator crypto API to generate the private key
946
- const key = new Uint8Array(32);
947
- globalThis.crypto.getRandomValues(key);
948
- return {
949
- privateKey: key,
950
- encodedPrivateKey: encodeRecoveryKey(key),
951
- };
952
- }
953
- }
954
-
955
- /**
956
- * Implementation of {@link CryptoApi#getEncryptionInfoForEvent}.
957
- */
958
- public async getEncryptionInfoForEvent(event: MatrixEvent): Promise<EventEncryptionInfo | null> {
959
- return this.eventDecryptor.getEncryptionInfoForEvent(event);
960
- }
961
-
962
- /**
963
- * Returns to-device verification requests that are already in progress for the given user id.
964
- *
965
- * Implementation of {@link CryptoApi#getVerificationRequestsToDeviceInProgress}
966
- *
967
- * @param userId - the ID of the user to query
968
- *
969
- * @returns the VerificationRequests that are in progress
970
- */
971
- public getVerificationRequestsToDeviceInProgress(userId: string): VerificationRequest[] {
972
- const requests: RustSdkCryptoJs.VerificationRequest[] = this.olmMachine.getVerificationRequests(
973
- new RustSdkCryptoJs.UserId(userId),
974
- );
975
- return requests
976
- .filter((request) => request.roomId === undefined)
977
- .map(
978
- (request) =>
979
- new RustVerificationRequest(
980
- this.olmMachine,
981
- request,
982
- this.outgoingRequestProcessor,
983
- this._supportedVerificationMethods,
984
- ),
985
- );
986
- }
987
-
988
- /**
989
- * Finds a DM verification request that is already in progress for the given room id
990
- *
991
- * Implementation of {@link CryptoApi#findVerificationRequestDMInProgress}
992
- *
993
- * @param roomId - the room to use for verification
994
- * @param userId - search the verification request for the given user
995
- *
996
- * @returns the VerificationRequest that is in progress, if any
997
- *
998
- */
999
- public findVerificationRequestDMInProgress(roomId: string, userId?: string): VerificationRequest | undefined {
1000
- if (!userId) throw new Error("missing userId");
1001
-
1002
- const requests: RustSdkCryptoJs.VerificationRequest[] = this.olmMachine.getVerificationRequests(
1003
- new RustSdkCryptoJs.UserId(userId),
1004
- );
1005
-
1006
- // Search for the verification request for the given room id
1007
- const request = requests.find((request) => request.roomId?.toString() === roomId);
1008
-
1009
- if (request) {
1010
- return new RustVerificationRequest(
1011
- this.olmMachine,
1012
- request,
1013
- this.outgoingRequestProcessor,
1014
- this._supportedVerificationMethods,
1015
- );
1016
- }
1017
- }
1018
-
1019
- /**
1020
- * Implementation of {@link CryptoApi#requestVerificationDM}
1021
- */
1022
- public async requestVerificationDM(userId: string, roomId: string): Promise<VerificationRequest> {
1023
- const userIdentity: RustSdkCryptoJs.UserIdentity | undefined = await this.olmMachine.getIdentity(
1024
- new RustSdkCryptoJs.UserId(userId),
1025
- );
1026
-
1027
- if (!userIdentity) throw new Error(`unknown userId ${userId}`);
1028
-
1029
- try {
1030
- // Transform the verification methods into rust objects
1031
- const methods = this._supportedVerificationMethods.map((method) =>
1032
- verificationMethodIdentifierToMethod(method),
1033
- );
1034
- // Get the request content to send to the DM room
1035
- const verificationEventContent: string = await userIdentity.verificationRequestContent(methods);
1036
-
1037
- // Send the request content to send to the DM room
1038
- const eventId = await this.sendVerificationRequestContent(roomId, verificationEventContent);
1039
-
1040
- // Get a verification request
1041
- const request: RustSdkCryptoJs.VerificationRequest = await userIdentity.requestVerification(
1042
- new RustSdkCryptoJs.RoomId(roomId),
1043
- new RustSdkCryptoJs.EventId(eventId),
1044
- methods,
1045
- );
1046
- return new RustVerificationRequest(
1047
- this.olmMachine,
1048
- request,
1049
- this.outgoingRequestProcessor,
1050
- this._supportedVerificationMethods,
1051
- );
1052
- } finally {
1053
- userIdentity.free();
1054
- }
1055
- }
1056
-
1057
- /**
1058
- * Send the verification content to a room
1059
- * See https://spec.matrix.org/v1.7/client-server-api/#put_matrixclientv3roomsroomidsendeventtypetxnid
1060
- *
1061
- * Prefer to use {@link OutgoingRequestProcessor.makeOutgoingRequest} when dealing with {@link RustSdkCryptoJs.RoomMessageRequest}
1062
- *
1063
- * @param roomId - the targeted room
1064
- * @param verificationEventContent - the request body.
1065
- *
1066
- * @returns the event id
1067
- */
1068
- private async sendVerificationRequestContent(roomId: string, verificationEventContent: string): Promise<string> {
1069
- const txId = randomString(32);
1070
- // Send the verification request content to the DM room
1071
- const { event_id: eventId } = await this.http.authedRequest<{ event_id: string }>(
1072
- Method.Put,
1073
- `/_matrix/client/v3/rooms/${encodeURIComponent(roomId)}/send/m.room.message/${encodeURIComponent(txId)}`,
1074
- undefined,
1075
- verificationEventContent,
1076
- {
1077
- prefix: "",
1078
- },
1079
- );
1080
-
1081
- return eventId;
1082
- }
1083
-
1084
- /**
1085
- * The verification methods we offer to the other side during an interactive verification.
1086
- */
1087
- private _supportedVerificationMethods: string[] = ALL_VERIFICATION_METHODS;
1088
-
1089
- /**
1090
- * Set the verification methods we offer to the other side during an interactive verification.
1091
- *
1092
- * If `undefined`, we will offer all the methods supported by the Rust SDK.
1093
- */
1094
- public setSupportedVerificationMethods(methods: string[] | undefined): void {
1095
- // by default, the Rust SDK does not offer `m.qr_code.scan.v1`, but we do want to offer that.
1096
- this._supportedVerificationMethods = methods ?? ALL_VERIFICATION_METHODS;
1097
- }
1098
-
1099
- /**
1100
- * Send a verification request to our other devices.
1101
- *
1102
- * If a verification is already in flight, returns it. Otherwise, initiates a new one.
1103
- *
1104
- * Implementation of {@link CryptoApi#requestOwnUserVerification}.
1105
- *
1106
- * @returns a VerificationRequest when the request has been sent to the other party.
1107
- */
1108
- public async requestOwnUserVerification(): Promise<VerificationRequest> {
1109
- const userIdentity: RustSdkCryptoJs.OwnUserIdentity | undefined = await this.olmMachine.getIdentity(
1110
- new RustSdkCryptoJs.UserId(this.userId),
1111
- );
1112
- if (userIdentity === undefined) {
1113
- throw new Error("cannot request verification for this device when there is no existing cross-signing key");
1114
- }
1115
-
1116
- try {
1117
- const [request, outgoingRequest]: [RustSdkCryptoJs.VerificationRequest, RustSdkCryptoJs.ToDeviceRequest] =
1118
- await userIdentity.requestVerification(
1119
- this._supportedVerificationMethods.map(verificationMethodIdentifierToMethod),
1120
- );
1121
- await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest);
1122
- return new RustVerificationRequest(
1123
- this.olmMachine,
1124
- request,
1125
- this.outgoingRequestProcessor,
1126
- this._supportedVerificationMethods,
1127
- );
1128
- } finally {
1129
- userIdentity.free();
1130
- }
1131
- }
1132
-
1133
- /**
1134
- * Request an interactive verification with the given device.
1135
- *
1136
- * If a verification is already in flight, returns it. Otherwise, initiates a new one.
1137
- *
1138
- * Implementation of {@link CryptoApi#requestDeviceVerification}.
1139
- *
1140
- * @param userId - ID of the owner of the device to verify
1141
- * @param deviceId - ID of the device to verify
1142
- *
1143
- * @returns a VerificationRequest when the request has been sent to the other party.
1144
- */
1145
- public async requestDeviceVerification(userId: string, deviceId: string): Promise<VerificationRequest> {
1146
- const device: RustSdkCryptoJs.Device | undefined = await this.olmMachine.getDevice(
1147
- new RustSdkCryptoJs.UserId(userId),
1148
- new RustSdkCryptoJs.DeviceId(deviceId),
1149
- );
1150
-
1151
- if (!device) {
1152
- throw new Error("Not a known device");
1153
- }
1154
-
1155
- try {
1156
- const [request, outgoingRequest] = device.requestVerification(
1157
- this._supportedVerificationMethods.map(verificationMethodIdentifierToMethod),
1158
- );
1159
- await this.outgoingRequestProcessor.makeOutgoingRequest(outgoingRequest);
1160
- return new RustVerificationRequest(
1161
- this.olmMachine,
1162
- request,
1163
- this.outgoingRequestProcessor,
1164
- this._supportedVerificationMethods,
1165
- );
1166
- } finally {
1167
- device.free();
1168
- }
1169
- }
1170
-
1171
- /**
1172
- * Fetch the backup decryption key we have saved in our store.
1173
- *
1174
- * Implementation of {@link CryptoApi#getSessionBackupPrivateKey}.
1175
- *
1176
- * @returns the key, if any, or null
1177
- */
1178
- public async getSessionBackupPrivateKey(): Promise<Uint8Array | null> {
1179
- const backupKeys: RustSdkCryptoJs.BackupKeys = await this.olmMachine.getBackupKeys();
1180
- if (!backupKeys.decryptionKey) return null;
1181
- return Buffer.from(backupKeys.decryptionKey.toBase64(), "base64");
1182
- }
1183
-
1184
- /**
1185
- * Store the backup decryption key.
1186
- *
1187
- * Implementation of {@link CryptoApi#storeSessionBackupPrivateKey}.
1188
- *
1189
- * @param key - the backup decryption key
1190
- * @param version - the backup version for this key.
1191
- */
1192
- public async storeSessionBackupPrivateKey(key: Uint8Array, version?: string): Promise<void> {
1193
- const base64Key = encodeBase64(key);
1194
-
1195
- if (!version) {
1196
- throw new Error("storeSessionBackupPrivateKey: version is required");
1197
- }
1198
-
1199
- await this.backupManager.saveBackupDecryptionKey(
1200
- RustSdkCryptoJs.BackupDecryptionKey.fromBase64(base64Key),
1201
- version,
1202
- );
1203
- }
1204
-
1205
- /**
1206
- * Implementation of {@link CryptoApi#loadSessionBackupPrivateKeyFromSecretStorage}.
1207
- */
1208
- public async loadSessionBackupPrivateKeyFromSecretStorage(): Promise<void> {
1209
- const backupKey = await this.secretStorage.get("m.megolm_backup.v1");
1210
- if (!backupKey) {
1211
- throw new Error("loadSessionBackupPrivateKeyFromSecretStorage: missing decryption key in secret storage");
1212
- }
1213
-
1214
- const keyBackupInfo = await this.backupManager.getServerBackupInfo();
1215
- if (!keyBackupInfo || !keyBackupInfo.version) {
1216
- throw new Error("loadSessionBackupPrivateKeyFromSecretStorage: unable to get backup version");
1217
- }
1218
-
1219
- const backupDecryptionKey = RustSdkCryptoJs.BackupDecryptionKey.fromBase64(backupKey);
1220
- if (!decryptionKeyMatchesKeyBackupInfo(backupDecryptionKey, keyBackupInfo)) {
1221
- throw new Error("loadSessionBackupPrivateKeyFromSecretStorage: decryption key does not match backup info");
1222
- }
1223
-
1224
- await this.backupManager.saveBackupDecryptionKey(backupDecryptionKey, keyBackupInfo.version);
1225
- }
1226
-
1227
- /**
1228
- * Get the current status of key backup.
1229
- *
1230
- * Implementation of {@link CryptoApi#getActiveSessionBackupVersion}.
1231
- */
1232
- public async getActiveSessionBackupVersion(): Promise<string | null> {
1233
- return await this.backupManager.getActiveBackupVersion();
1234
- }
1235
-
1236
- /**
1237
- * Implementation of {@link CryptoApi#getKeyBackupInfo}.
1238
- */
1239
- public async getKeyBackupInfo(): Promise<KeyBackupInfo | null> {
1240
- return (await this.backupManager.getServerBackupInfo()) || null;
1241
- }
1242
-
1243
- /**
1244
- * Determine if a key backup can be trusted.
1245
- *
1246
- * Implementation of {@link CryptoApi#isKeyBackupTrusted}.
1247
- */
1248
- public async isKeyBackupTrusted(info: KeyBackupInfo): Promise<BackupTrustInfo> {
1249
- return await this.backupManager.isKeyBackupTrusted(info);
1250
- }
1251
-
1252
- /**
1253
- * Force a re-check of the key backup and enable/disable it as appropriate.
1254
- *
1255
- * Implementation of {@link CryptoApi#checkKeyBackupAndEnable}.
1256
- */
1257
- public async checkKeyBackupAndEnable(): Promise<KeyBackupCheck | null> {
1258
- return await this.backupManager.checkKeyBackupAndEnable(true);
1259
- }
1260
-
1261
- /**
1262
- * Implementation of {@link CryptoApi#deleteKeyBackupVersion}.
1263
- */
1264
- public async deleteKeyBackupVersion(version: string): Promise<void> {
1265
- await this.backupManager.deleteKeyBackupVersion(version);
1266
- }
1267
-
1268
- /**
1269
- * Implementation of {@link CryptoApi#resetKeyBackup}.
1270
- */
1271
- public async resetKeyBackup(): Promise<void> {
1272
- const backupInfo = await this.backupManager.setupKeyBackup((o) => this.signObject(o));
1273
-
1274
- // we want to store the private key in 4S
1275
- // need to check if 4S is set up?
1276
- if (await this.secretStorageHasAESKey()) {
1277
- await this.secretStorage.store("m.megolm_backup.v1", backupInfo.decryptionKey.toBase64());
1278
- }
1279
-
1280
- // we can check and start async
1281
- this.checkKeyBackupAndEnable();
1282
- }
1283
-
1284
- /**
1285
- * Signs the given object with the current device and current identity (if available).
1286
- * As defined in {@link https://spec.matrix.org/v1.8/appendices/#signing-json | Signing JSON}.
1287
- *
1288
- * Helper for {@link RustCrypto#resetKeyBackup}.
1289
- *
1290
- * @param obj - The object to sign
1291
- */
1292
- private async signObject<T extends ISignableObject & object>(obj: T): Promise<void> {
1293
- const sigs = new Map(Object.entries(obj.signatures || {}));
1294
- const unsigned = obj.unsigned;
1295
-
1296
- delete obj.signatures;
1297
- delete obj.unsigned;
1298
-
1299
- const userSignatures = sigs.get(this.userId) || {};
1300
-
1301
- const canonalizedJson = anotherjson.stringify(obj);
1302
- const signatures: RustSdkCryptoJs.Signatures = await this.olmMachine.sign(canonalizedJson);
1303
-
1304
- const map = JSON.parse(signatures.asJSON());
1305
-
1306
- sigs.set(this.userId, { ...userSignatures, ...map[this.userId] });
1307
-
1308
- if (unsigned !== undefined) obj.unsigned = unsigned;
1309
- obj.signatures = Object.fromEntries(sigs.entries());
1310
- }
1311
-
1312
- /**
1313
- * Implementation of {@link CryptoApi#restoreKeyBackupWithPassphrase}.
1314
- */
1315
- public async restoreKeyBackupWithPassphrase(
1316
- passphrase: string,
1317
- opts?: KeyBackupRestoreOpts,
1318
- ): Promise<KeyBackupRestoreResult> {
1319
- const backupInfo = await this.backupManager.getServerBackupInfo();
1320
- if (!backupInfo?.version) {
1321
- throw new Error("No backup info available");
1322
- }
1323
-
1324
- const privateKey = await keyFromAuthData(backupInfo.auth_data, passphrase);
1325
-
1326
- // Cache the key
1327
- await this.storeSessionBackupPrivateKey(privateKey, backupInfo.version);
1328
- return this.restoreKeyBackup(opts);
1329
- }
1330
-
1331
- /**
1332
- * Implementation of {@link CryptoApi#restoreKeyBackup}.
1333
- */
1334
- public async restoreKeyBackup(opts?: KeyBackupRestoreOpts): Promise<KeyBackupRestoreResult> {
1335
- // Get the decryption key from the crypto store
1336
- const backupKeys: RustSdkCryptoJs.BackupKeys = await this.olmMachine.getBackupKeys();
1337
- const { decryptionKey, backupVersion } = backupKeys;
1338
- if (!decryptionKey || !backupVersion) throw new Error("No decryption key found in crypto store");
1339
-
1340
- const decodedDecryptionKey = decodeBase64(decryptionKey.toBase64());
1341
-
1342
- const backupInfo = await this.backupManager.requestKeyBackupVersion(backupVersion);
1343
- if (!backupInfo) throw new Error(`Backup version to restore ${backupVersion} not found on server`);
1344
-
1345
- const backupDecryptor = await this.getBackupDecryptor(backupInfo, decodedDecryptionKey);
1346
-
1347
- try {
1348
- opts?.progressCallback?.({
1349
- stage: "fetch",
1350
- });
1351
-
1352
- return await this.backupManager.restoreKeyBackup(backupVersion, backupDecryptor, opts);
1353
- } finally {
1354
- // Free to avoid to keep in memory the decryption key stored in it. To avoid to exposing it to an attacker.
1355
- backupDecryptor.free();
1356
- }
1357
- }
1358
-
1359
- /**
1360
- * Implementation of {@link CryptoApi#isDehydrationSupported}.
1361
- */
1362
- public async isDehydrationSupported(): Promise<boolean> {
1363
- return await this.dehydratedDeviceManager.isSupported();
1364
- }
1365
-
1366
- /**
1367
- * Implementation of {@link CryptoApi#startDehydration}.
1368
- */
1369
- public async startDehydration(createNewKey?: boolean): Promise<void> {
1370
- if (!(await this.isCrossSigningReady()) || !(await this.isSecretStorageReady())) {
1371
- throw new Error("Device dehydration requires cross-signing and secret storage to be set up");
1372
- }
1373
- return await this.dehydratedDeviceManager.start(createNewKey);
1374
- }
1375
-
1376
- /**
1377
- * Implementation of {@link CryptoApi#importSecretsBundle}.
1378
- */
1379
- public async importSecretsBundle(
1380
- secrets: Parameters<NonNullable<CryptoApi["importSecretsBundle"]>>[0],
1381
- ): Promise<void> {
1382
- const secretsBundle = RustSdkCryptoJs.SecretsBundle.from_json(secrets);
1383
- await this.getOlmMachineOrThrow().importSecretsBundle(secretsBundle); // this method frees the SecretsBundle
1384
- }
1385
-
1386
- /**
1387
- * Implementation of {@link CryptoApi#exportSecretsBundle}.
1388
- */
1389
- public async exportSecretsBundle(): ReturnType<NonNullable<CryptoApi["exportSecretsBundle"]>> {
1390
- const secretsBundle = await this.getOlmMachineOrThrow().exportSecretsBundle();
1391
- const secrets = secretsBundle.to_json();
1392
- secretsBundle.free();
1393
- return secrets;
1394
- }
1395
-
1396
- /**
1397
- * Implementation of {@link CryptoApi#encryptToDeviceMessages}.
1398
- */
1399
- public async encryptToDeviceMessages(
1400
- eventType: string,
1401
- devices: { userId: string; deviceId: string }[],
1402
- payload: ToDevicePayload,
1403
- ): Promise<ToDeviceBatch> {
1404
- const logger = new LogSpan(this.logger, "encryptToDeviceMessages");
1405
- const uniqueUsers = new Set(devices.map(({ userId }) => userId));
1406
-
1407
- // This will ensure we have Olm sessions for all of the users' devices.
1408
- // However, we only care about some of the devices.
1409
- // So, perhaps we can optimise this later on.
1410
- await this.keyClaimManager.ensureSessionsForUsers(
1411
- logger,
1412
- Array.from(uniqueUsers).map((userId) => new RustSdkCryptoJs.UserId(userId)),
1413
- );
1414
- const batch: ToDeviceBatch = {
1415
- batch: [],
1416
- eventType: EventType.RoomMessageEncrypted,
1417
- };
1418
-
1419
- await Promise.all(
1420
- devices.map(async ({ userId, deviceId }) => {
1421
- const device: RustSdkCryptoJs.Device | undefined = await this.olmMachine.getDevice(
1422
- new RustSdkCryptoJs.UserId(userId),
1423
- new RustSdkCryptoJs.DeviceId(deviceId),
1424
- );
1425
-
1426
- if (device) {
1427
- const encryptedPayload = JSON.parse(await device.encryptToDeviceEvent(eventType, payload));
1428
- batch.batch.push({
1429
- deviceId,
1430
- userId,
1431
- payload: encryptedPayload,
1432
- });
1433
- } else {
1434
- this.logger.warn(`encryptToDeviceMessages: unknown device ${userId}:${deviceId}`);
1435
- }
1436
- }),
1437
- );
1438
-
1439
- return batch;
1440
- }
1441
-
1442
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1443
- //
1444
- // SyncCryptoCallbacks implementation
1445
- //
1446
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1447
-
1448
- /**
1449
- * Apply sync changes to the olm machine
1450
- * @param events - the received to-device messages
1451
- * @param oneTimeKeysCounts - the received one time key counts
1452
- * @param unusedFallbackKeys - the received unused fallback keys
1453
- * @param devices - the received device list updates
1454
- * @returns A list of preprocessed to-device messages.
1455
- */
1456
- private async receiveSyncChanges({
1457
- events,
1458
- oneTimeKeysCounts = new Map<string, number>(),
1459
- unusedFallbackKeys,
1460
- devices = new RustSdkCryptoJs.DeviceLists(),
1461
- }: {
1462
- events?: IToDeviceEvent[];
1463
- oneTimeKeysCounts?: Map<string, number>;
1464
- unusedFallbackKeys?: Set<string>;
1465
- devices?: RustSdkCryptoJs.DeviceLists;
1466
- }): Promise<IToDeviceEvent[]> {
1467
- const result = await logDuration(logger, "receiveSyncChanges", async () => {
1468
- return await this.olmMachine.receiveSyncChanges(
1469
- events ? JSON.stringify(events) : "[]",
1470
- devices,
1471
- oneTimeKeysCounts,
1472
- unusedFallbackKeys,
1473
- );
1474
- });
1475
-
1476
- // receiveSyncChanges returns a JSON-encoded list of decrypted to-device messages.
1477
- return JSON.parse(result);
1478
- }
1479
-
1480
- /** called by the sync loop to preprocess incoming to-device messages
1481
- *
1482
- * @param events - the received to-device messages
1483
- * @returns A list of preprocessed to-device messages.
1484
- */
1485
- public async preprocessToDeviceMessages(events: IToDeviceEvent[]): Promise<IToDeviceEvent[]> {
1486
- // send the received to-device messages into receiveSyncChanges. We have no info on device-list changes,
1487
- // one-time-keys, or fallback keys, so just pass empty data.
1488
- const processed = await this.receiveSyncChanges({ events });
1489
-
1490
- // look for interesting to-device messages
1491
- for (const message of processed) {
1492
- if (message.type === EventType.KeyVerificationRequest) {
1493
- const sender = message.sender;
1494
- const transactionId = message.content.transaction_id;
1495
- if (transactionId && sender) {
1496
- this.onIncomingKeyVerificationRequest(sender, transactionId);
1497
- }
1498
- }
1499
- }
1500
- return processed;
1501
- }
1502
-
1503
- /** called by the sync loop to process one time key counts and unused fallback keys
1504
- *
1505
- * @param oneTimeKeysCounts - the received one time key counts
1506
- * @param unusedFallbackKeys - the received unused fallback keys
1507
- */
1508
- public async processKeyCounts(
1509
- oneTimeKeysCounts?: Record<string, number>,
1510
- unusedFallbackKeys?: string[],
1511
- ): Promise<void> {
1512
- const mapOneTimeKeysCount = oneTimeKeysCounts && new Map<string, number>(Object.entries(oneTimeKeysCounts));
1513
- const setUnusedFallbackKeys = unusedFallbackKeys && new Set<string>(unusedFallbackKeys);
1514
-
1515
- if (mapOneTimeKeysCount !== undefined || setUnusedFallbackKeys !== undefined) {
1516
- await this.receiveSyncChanges({
1517
- oneTimeKeysCounts: mapOneTimeKeysCount,
1518
- unusedFallbackKeys: setUnusedFallbackKeys,
1519
- });
1520
- }
1521
- }
1522
-
1523
- /** called by the sync loop to process the notification that device lists have
1524
- * been changed.
1525
- *
1526
- * @param deviceLists - device_lists field from /sync
1527
- */
1528
- public async processDeviceLists(deviceLists: IDeviceLists): Promise<void> {
1529
- const devices = new RustSdkCryptoJs.DeviceLists(
1530
- deviceLists.changed?.map((userId) => new RustSdkCryptoJs.UserId(userId)),
1531
- deviceLists.left?.map((userId) => new RustSdkCryptoJs.UserId(userId)),
1532
- );
1533
- await this.receiveSyncChanges({ devices });
1534
- }
1535
-
1536
- /** called by the sync loop on m.room.encrypted events
1537
- *
1538
- * @param room - in which the event was received
1539
- * @param event - encryption event to be processed
1540
- */
1541
- public async onCryptoEvent(room: Room, event: MatrixEvent): Promise<void> {
1542
- const config = event.getContent();
1543
- const settings = new RustSdkCryptoJs.RoomSettings();
1544
-
1545
- if (config.algorithm === "m.megolm.v1.aes-sha2") {
1546
- settings.algorithm = RustSdkCryptoJs.EncryptionAlgorithm.MegolmV1AesSha2;
1547
- } else {
1548
- // Among other situations, this happens if the crypto state event is redacted.
1549
- this.logger.warn(`Room ${room.roomId}: ignoring crypto event with invalid algorithm ${config.algorithm}`);
1550
- return;
1551
- }
1552
-
1553
- try {
1554
- settings.sessionRotationPeriodMs = config.rotation_period_ms;
1555
- settings.sessionRotationPeriodMessages = config.rotation_period_msgs;
1556
- await this.olmMachine.setRoomSettings(new RustSdkCryptoJs.RoomId(room.roomId), settings);
1557
- } catch (e) {
1558
- this.logger.warn(`Room ${room.roomId}: ignoring crypto event which caused error: ${e}`);
1559
- return;
1560
- }
1561
-
1562
- // If we got this far, the SDK found the event acceptable.
1563
- // We need to either create or update the active RoomEncryptor.
1564
- const existingEncryptor = this.roomEncryptors[room.roomId];
1565
- if (existingEncryptor) {
1566
- existingEncryptor.onCryptoEvent(config);
1567
- } else {
1568
- this.roomEncryptors[room.roomId] = new RoomEncryptor(
1569
- this.olmMachine,
1570
- this.keyClaimManager,
1571
- this.outgoingRequestsManager,
1572
- room,
1573
- config,
1574
- );
1575
- }
1576
- }
1577
-
1578
- /** called by the sync loop after processing each sync.
1579
- *
1580
- * TODO: figure out something equivalent for sliding sync.
1581
- *
1582
- * @param syncState - information on the completed sync.
1583
- */
1584
- public onSyncCompleted(syncState: OnSyncCompletedData): void {
1585
- // Processing the /sync may have produced new outgoing requests which need sending, so kick off the outgoing
1586
- // request loop, if it's not already running.
1587
- this.outgoingRequestsManager.doProcessOutgoingRequests().catch((e) => {
1588
- this.logger.warn("onSyncCompleted: Error processing outgoing requests", e);
1589
- });
1590
- }
1591
-
1592
- /**
1593
- * Handle an incoming m.key.verification.request event, received either in-room or in a to-device message.
1594
- *
1595
- * @param sender - the sender of the event
1596
- * @param transactionId - the transaction ID for the verification. For to-device messages, this comes from the
1597
- * content of the message; for in-room messages it is the event ID.
1598
- */
1599
- private onIncomingKeyVerificationRequest(sender: string, transactionId: string): void {
1600
- const request: RustSdkCryptoJs.VerificationRequest | undefined = this.olmMachine.getVerificationRequest(
1601
- new RustSdkCryptoJs.UserId(sender),
1602
- transactionId,
1603
- );
1604
-
1605
- if (request) {
1606
- this.emit(
1607
- CryptoEvent.VerificationRequestReceived,
1608
- new RustVerificationRequest(
1609
- this.olmMachine,
1610
- request,
1611
- this.outgoingRequestProcessor,
1612
- this._supportedVerificationMethods,
1613
- ),
1614
- );
1615
- } else {
1616
- // There are multiple reasons this can happen; probably the most likely is that the event is an
1617
- // in-room event which is too old.
1618
- this.logger.info(
1619
- `Ignoring just-received verification request ${transactionId} which did not start a rust-side verification`,
1620
- );
1621
- }
1622
- }
1623
-
1624
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1625
- //
1626
- // Other public functions
1627
- //
1628
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1629
-
1630
- /** called by the MatrixClient on a room membership event
1631
- *
1632
- * @param event - The matrix event which caused this event to fire.
1633
- * @param member - The member whose RoomMember.membership changed.
1634
- * @param oldMembership - The previous membership state. Null if it's a new member.
1635
- */
1636
- public onRoomMembership(event: MatrixEvent, member: RoomMember, oldMembership?: string): void {
1637
- const enc = this.roomEncryptors[event.getRoomId()!];
1638
- if (!enc) {
1639
- // not encrypting in this room
1640
- return;
1641
- }
1642
- enc.onRoomMembership(member);
1643
- }
1644
-
1645
- /** Callback for OlmMachine.registerRoomKeyUpdatedCallback
1646
- *
1647
- * Called by the rust-sdk whenever there is an update to (megolm) room keys. We
1648
- * check if we have any events waiting for the given keys, and schedule them for
1649
- * a decryption retry if so.
1650
- *
1651
- * @param keys - details of the updated keys
1652
- */
1653
- public async onRoomKeysUpdated(keys: RustSdkCryptoJs.RoomKeyInfo[]): Promise<void> {
1654
- for (const key of keys) {
1655
- this.onRoomKeyUpdated(key);
1656
- }
1657
- this.backupManager.maybeUploadKey();
1658
- }
1659
-
1660
- private onRoomKeyUpdated(key: RustSdkCryptoJs.RoomKeyInfo): void {
1661
- if (this.stopped) return;
1662
- this.logger.debug(
1663
- `Got update for session ${key.sessionId} from sender ${key.senderKey.toBase64()} in ${key.roomId.toString()}`,
1664
- );
1665
- const pendingList = this.eventDecryptor.getEventsPendingRoomKey(key.roomId.toString(), key.sessionId);
1666
- if (pendingList.length === 0) return;
1667
-
1668
- this.logger.debug(
1669
- "Retrying decryption on events:",
1670
- pendingList.map((e) => `${e.getId()}`),
1671
- );
1672
-
1673
- // Have another go at decrypting events with this key.
1674
- //
1675
- // We don't want to end up blocking the callback from Rust, which could otherwise end up dropping updates,
1676
- // so we don't wait for the decryption to complete. In any case, there is no need to wait:
1677
- // MatrixEvent.attemptDecryption ensures that there is only one decryption attempt happening at once,
1678
- // and deduplicates repeated attempts for the same event.
1679
- for (const ev of pendingList) {
1680
- ev.attemptDecryption(this, { isRetry: true }).catch((_e) => {
1681
- this.logger.info(`Still unable to decrypt event ${ev.getId()} after receiving key`);
1682
- });
1683
- }
1684
- }
1685
-
1686
- /**
1687
- * Callback for `OlmMachine.registerRoomKeyWithheldCallback`.
1688
- *
1689
- * Called by the rust sdk whenever we are told that a key has been withheld. We see if we had any events that
1690
- * failed to decrypt for the given session, and update their status if so.
1691
- *
1692
- * @param withheld - Details of the withheld sessions.
1693
- */
1694
- public async onRoomKeysWithheld(withheld: RustSdkCryptoJs.RoomKeyWithheldInfo[]): Promise<void> {
1695
- for (const session of withheld) {
1696
- this.logger.debug(`Got withheld message for session ${session.sessionId} in ${session.roomId.toString()}`);
1697
- const pendingList = this.eventDecryptor.getEventsPendingRoomKey(
1698
- session.roomId.toString(),
1699
- session.sessionId,
1700
- );
1701
- if (pendingList.length === 0) return;
1702
-
1703
- // The easiest way to update the status of the event is to have another go at decrypting it.
1704
- this.logger.debug(
1705
- "Retrying decryption on events:",
1706
- pendingList.map((e) => `${e.getId()}`),
1707
- );
1708
-
1709
- for (const ev of pendingList) {
1710
- ev.attemptDecryption(this, { isRetry: true }).catch((_e) => {
1711
- // It's somewhat expected that we still can't decrypt here.
1712
- });
1713
- }
1714
- }
1715
- }
1716
-
1717
- /**
1718
- * Callback for `OlmMachine.registerUserIdentityUpdatedCallback`
1719
- *
1720
- * Called by the rust-sdk whenever there is an update to any user's cross-signing status. We re-check their trust
1721
- * status and emit a `UserTrustStatusChanged` event, as well as a `KeysChanged` if it is our own identity that changed.
1722
- *
1723
- * @param userId - the user with the updated identity
1724
- */
1725
- public async onUserIdentityUpdated(userId: RustSdkCryptoJs.UserId): Promise<void> {
1726
- const newVerification = await this.getUserVerificationStatus(userId.toString());
1727
- this.emit(CryptoEvent.UserTrustStatusChanged, userId.toString(), newVerification);
1728
-
1729
- // If our own user identity has changed, we may now trust the key backup where we did not before.
1730
- // So, re-check the key backup status and enable it if available.
1731
- if (userId.toString() === this.userId) {
1732
- this.emit(CryptoEvent.KeysChanged, {});
1733
- await this.checkKeyBackupAndEnable();
1734
- }
1735
- }
1736
-
1737
- /**
1738
- * Callback for `OlmMachine.registerDevicesUpdatedCallback`
1739
- *
1740
- * Called when users' devices have updated. Emits `WillUpdateDevices` and `DevicesUpdated`. In the JavaScript
1741
- * crypto backend, these events are called at separate times, with `WillUpdateDevices` being emitted just before
1742
- * the devices are saved, and `DevicesUpdated` being emitted just after. But the OlmMachine only gives us
1743
- * one event, so we emit both events here.
1744
- *
1745
- * @param userIds - an array of user IDs of users whose devices have updated.
1746
- */
1747
- public async onDevicesUpdated(userIds: string[]): Promise<void> {
1748
- this.emit(CryptoEvent.WillUpdateDevices, userIds, false);
1749
- this.emit(CryptoEvent.DevicesUpdated, userIds, false);
1750
- }
1751
-
1752
- /**
1753
- * Handles secret received from the rust secret inbox.
1754
- *
1755
- * The gossipped secrets are received using the `m.secret.send` event type
1756
- * and are guaranteed to have been received over a 1-to-1 Olm
1757
- * Session from a verified device.
1758
- *
1759
- * The only secret currently handled in this way is `m.megolm_backup.v1`.
1760
- *
1761
- * @param name - the secret name
1762
- * @param value - the secret value
1763
- */
1764
- private async handleSecretReceived(name: string, value: string): Promise<boolean> {
1765
- this.logger.debug(`onReceiveSecret: Received secret ${name}`);
1766
- if (name === "m.megolm_backup.v1") {
1767
- return await this.backupManager.handleBackupSecretReceived(value);
1768
- // XXX at this point we should probably try to download the backup and import the keys,
1769
- // or at least retry for the current decryption failures?
1770
- // Maybe add some signaling when a new secret is received, and let clients handle it?
1771
- // as it's where the restore from backup APIs are exposed.
1772
- }
1773
- return false;
1774
- }
1775
-
1776
- /**
1777
- * Called when a new secret is received in the rust secret inbox.
1778
- *
1779
- * Will poll the secret inbox and handle the secrets received.
1780
- *
1781
- * @param name - The name of the secret received.
1782
- */
1783
- public async checkSecrets(name: string): Promise<void> {
1784
- const pendingValues: string[] = await this.olmMachine.getSecretsFromInbox(name);
1785
- for (const value of pendingValues) {
1786
- if (await this.handleSecretReceived(name, value)) {
1787
- // If we have a valid secret for that name there is no point of processing the other secrets values.
1788
- // It's probably the same secret shared by another device.
1789
- break;
1790
- }
1791
- }
1792
-
1793
- // Important to call this after handling the secrets as good hygiene.
1794
- await this.olmMachine.deleteSecretsFromInbox(name);
1795
- }
1796
-
1797
- /**
1798
- * Handle a live event received via /sync.
1799
- * See {@link ClientEventHandlerMap#event}
1800
- *
1801
- * @param event - live event
1802
- */
1803
- public async onLiveEventFromSync(event: MatrixEvent): Promise<void> {
1804
- // Ignore state event or remote echo
1805
- // transaction_id is provided in case of remote echo {@link https://spec.matrix.org/v1.7/client-server-api/#local-echo}
1806
- if (event.isState() || !!event.getUnsigned().transaction_id) return;
1807
-
1808
- const processEvent = async (evt: MatrixEvent): Promise<void> => {
1809
- // Process only verification event
1810
- if (isVerificationEvent(event)) {
1811
- await this.onKeyVerificationEvent(evt);
1812
- }
1813
- };
1814
-
1815
- // If the event is encrypted of in failure, we wait for decryption
1816
- if (event.isDecryptionFailure() || event.isEncrypted()) {
1817
- // 5 mins
1818
- const TIMEOUT_DELAY = 5 * 60 * 1000;
1819
-
1820
- // After 5mins, we are not expecting the event to be decrypted
1821
- const timeoutId = setTimeout(() => event.off(MatrixEventEvent.Decrypted, onDecrypted), TIMEOUT_DELAY);
1822
-
1823
- const onDecrypted = (decryptedEvent: MatrixEvent, error?: Error): void => {
1824
- if (error) return;
1825
-
1826
- clearTimeout(timeoutId);
1827
- event.off(MatrixEventEvent.Decrypted, onDecrypted);
1828
- processEvent(decryptedEvent);
1829
- };
1830
-
1831
- event.on(MatrixEventEvent.Decrypted, onDecrypted);
1832
- } else {
1833
- await processEvent(event);
1834
- }
1835
- }
1836
-
1837
- /**
1838
- * Handle an in-room key verification event.
1839
- *
1840
- * @param event - a key validation request event.
1841
- */
1842
- private async onKeyVerificationEvent(event: MatrixEvent): Promise<void> {
1843
- const roomId = event.getRoomId();
1844
-
1845
- if (!roomId) {
1846
- throw new Error("missing roomId in the event");
1847
- }
1848
-
1849
- this.logger.debug(
1850
- `Incoming verification event ${event.getId()} type ${event.getType()} from ${event.getSender()}`,
1851
- );
1852
-
1853
- await this.olmMachine.receiveVerificationEvent(
1854
- JSON.stringify({
1855
- event_id: event.getId(),
1856
- type: event.getType(),
1857
- sender: event.getSender(),
1858
- state_key: event.getStateKey(),
1859
- content: event.getContent(),
1860
- origin_server_ts: event.getTs(),
1861
- }),
1862
- new RustSdkCryptoJs.RoomId(roomId),
1863
- );
1864
-
1865
- if (
1866
- event.getType() === EventType.RoomMessage &&
1867
- event.getContent().msgtype === MsgType.KeyVerificationRequest
1868
- ) {
1869
- this.onIncomingKeyVerificationRequest(event.getSender()!, event.getId()!);
1870
- }
1871
-
1872
- // that may have caused us to queue up outgoing requests, so make sure we send them.
1873
- this.outgoingRequestsManager.doProcessOutgoingRequests().catch((e) => {
1874
- this.logger.warn("onKeyVerificationRequest: Error processing outgoing requests", e);
1875
- });
1876
- }
1877
-
1878
- /**
1879
- * Returns the cross-signing user identity of the current user.
1880
- *
1881
- * Not part of the public crypto-api interface.
1882
- * Used during migration from legacy js-crypto to update local trust if needed.
1883
- */
1884
- public async getOwnIdentity(): Promise<RustSdkCryptoJs.OwnUserIdentity | undefined> {
1885
- return await this.olmMachine.getIdentity(new RustSdkCryptoJs.UserId(this.userId));
1886
- }
1887
- }
1888
-
1889
- class EventDecryptor {
1890
- /**
1891
- * Events which we couldn't decrypt due to unknown sessions / indexes.
1892
- *
1893
- * Map from roomId to sessionId to Set of MatrixEvents
1894
- */
1895
- private eventsPendingKey = new MapWithDefault<string, MapWithDefault<string, Set<MatrixEvent>>>(
1896
- () => new MapWithDefault<string, Set<MatrixEvent>>(() => new Set()),
1897
- );
1898
-
1899
- public constructor(
1900
- private readonly logger: Logger,
1901
- private readonly olmMachine: RustSdkCryptoJs.OlmMachine,
1902
- private readonly perSessionBackupDownloader: PerSessionKeyBackupDownloader,
1903
- ) {}
1904
-
1905
- public async attemptEventDecryption(
1906
- event: MatrixEvent,
1907
- isolationMode: DeviceIsolationMode,
1908
- ): Promise<IEventDecryptionResult> {
1909
- // add the event to the pending list *before* attempting to decrypt.
1910
- // then, if the key turns up while decryption is in progress (and
1911
- // decryption fails), we will schedule a retry.
1912
- // (fixes https://github.com/vector-im/element-web/issues/5001)
1913
- this.addEventToPendingList(event);
1914
-
1915
- let trustRequirement;
1916
-
1917
- switch (isolationMode.kind) {
1918
- case DeviceIsolationModeKind.AllDevicesIsolationMode:
1919
- trustRequirement = RustSdkCryptoJs.TrustRequirement.Untrusted;
1920
- break;
1921
- case DeviceIsolationModeKind.OnlySignedDevicesIsolationMode:
1922
- trustRequirement = RustSdkCryptoJs.TrustRequirement.CrossSignedOrLegacy;
1923
- break;
1924
- }
1925
-
1926
- try {
1927
- const res = (await this.olmMachine.decryptRoomEvent(
1928
- stringifyEvent(event),
1929
- new RustSdkCryptoJs.RoomId(event.getRoomId()!),
1930
- new RustSdkCryptoJs.DecryptionSettings(trustRequirement),
1931
- )) as RustSdkCryptoJs.DecryptedRoomEvent;
1932
-
1933
- // Success. We can remove the event from the pending list, if
1934
- // that hasn't already happened.
1935
- this.removeEventFromPendingList(event);
1936
-
1937
- return {
1938
- clearEvent: JSON.parse(res.event),
1939
- claimedEd25519Key: res.senderClaimedEd25519Key,
1940
- senderCurve25519Key: res.senderCurve25519Key,
1941
- forwardingCurve25519KeyChain: res.forwardingCurve25519KeyChain,
1942
- };
1943
- } catch (err) {
1944
- if (err instanceof RustSdkCryptoJs.MegolmDecryptionError) {
1945
- this.onMegolmDecryptionError(event, err, await this.perSessionBackupDownloader.getServerBackupInfo());
1946
- } else {
1947
- throw new DecryptionError(DecryptionFailureCode.UNKNOWN_ERROR, "Unknown error");
1948
- }
1949
- }
1950
- }
1951
-
1952
- /**
1953
- * Handle a `MegolmDecryptionError` returned by the rust SDK.
1954
- *
1955
- * Fires off a request to the `perSessionBackupDownloader`, if appropriate, and then throws a `DecryptionError`.
1956
- *
1957
- * @param event - The event which could not be decrypted.
1958
- * @param err - The error from the Rust SDK.
1959
- * @param serverBackupInfo - Details about the current backup from the server. `null` if there is no backup.
1960
- * `undefined` if our attempt to check failed.
1961
- */
1962
- private onMegolmDecryptionError(
1963
- event: MatrixEvent,
1964
- err: RustSdkCryptoJs.MegolmDecryptionError,
1965
- serverBackupInfo: KeyBackupInfo | null | undefined,
1966
- ): never {
1967
- const content = event.getWireContent();
1968
- const errorDetails = { sender_key: content.sender_key, session_id: content.session_id };
1969
-
1970
- // If the error looks like it might be recoverable from backup, queue up a request to try that.
1971
- if (
1972
- err.code === RustSdkCryptoJs.DecryptionErrorCode.MissingRoomKey ||
1973
- err.code === RustSdkCryptoJs.DecryptionErrorCode.UnknownMessageIndex
1974
- ) {
1975
- this.perSessionBackupDownloader.onDecryptionKeyMissingError(event.getRoomId()!, content.session_id!);
1976
-
1977
- // If the server is telling us our membership at the time the event
1978
- // was sent, and it isn't "join", we use a different error code.
1979
- const membership = event.getMembershipAtEvent();
1980
- if (membership && membership !== KnownMembership.Join && membership !== KnownMembership.Invite) {
1981
- throw new DecryptionError(
1982
- DecryptionFailureCode.HISTORICAL_MESSAGE_USER_NOT_JOINED,
1983
- "This message was sent when we were not a member of the room.",
1984
- errorDetails,
1985
- );
1986
- }
1987
-
1988
- // If the event was sent before this device was created, we use some different error codes.
1989
- if (event.getTs() <= this.olmMachine.deviceCreationTimeMs) {
1990
- if (serverBackupInfo === null) {
1991
- throw new DecryptionError(
1992
- DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP,
1993
- "This message was sent before this device logged in, and there is no key backup on the server.",
1994
- errorDetails,
1995
- );
1996
- } else if (!this.perSessionBackupDownloader.isKeyBackupDownloadConfigured()) {
1997
- throw new DecryptionError(
1998
- DecryptionFailureCode.HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED,
1999
- "This message was sent before this device logged in, and key backup is not working.",
2000
- errorDetails,
2001
- );
2002
- } else {
2003
- throw new DecryptionError(
2004
- DecryptionFailureCode.HISTORICAL_MESSAGE_WORKING_BACKUP,
2005
- "This message was sent before this device logged in. Key backup is working, but we still do not (yet) have the key.",
2006
- errorDetails,
2007
- );
2008
- }
2009
- }
2010
- }
2011
-
2012
- // If we got a withheld code, expose that.
2013
- if (err.maybe_withheld) {
2014
- // Unfortunately the Rust SDK API doesn't let us distinguish between different withheld cases, other than
2015
- // by string-matching.
2016
- const failureCode =
2017
- err.maybe_withheld === "The sender has disabled encrypting to unverified devices."
2018
- ? DecryptionFailureCode.MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE
2019
- : DecryptionFailureCode.MEGOLM_KEY_WITHHELD;
2020
- throw new DecryptionError(failureCode, err.maybe_withheld, errorDetails);
2021
- }
2022
-
2023
- switch (err.code) {
2024
- case RustSdkCryptoJs.DecryptionErrorCode.MissingRoomKey:
2025
- throw new DecryptionError(
2026
- DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID,
2027
- "The sender's device has not sent us the keys for this message.",
2028
- errorDetails,
2029
- );
2030
-
2031
- case RustSdkCryptoJs.DecryptionErrorCode.UnknownMessageIndex:
2032
- throw new DecryptionError(
2033
- DecryptionFailureCode.OLM_UNKNOWN_MESSAGE_INDEX,
2034
- "The sender's device has not sent us the keys for this message at this index.",
2035
- errorDetails,
2036
- );
2037
-
2038
- case RustSdkCryptoJs.DecryptionErrorCode.SenderIdentityPreviouslyVerified:
2039
- // We're refusing to decrypt due to not trusting the sender,
2040
- // rather than failing to decrypt due to lack of keys, so we
2041
- // don't need to keep it on the pending list.
2042
- this.removeEventFromPendingList(event);
2043
- throw new DecryptionError(
2044
- DecryptionFailureCode.SENDER_IDENTITY_PREVIOUSLY_VERIFIED,
2045
- "The sender identity is unverified, but was previously verified.",
2046
- );
2047
-
2048
- case RustSdkCryptoJs.DecryptionErrorCode.UnknownSenderDevice:
2049
- // We're refusing to decrypt due to not trusting the sender,
2050
- // rather than failing to decrypt due to lack of keys, so we
2051
- // don't need to keep it on the pending list.
2052
- this.removeEventFromPendingList(event);
2053
- throw new DecryptionError(
2054
- DecryptionFailureCode.UNKNOWN_SENDER_DEVICE,
2055
- "The sender device is not known.",
2056
- );
2057
-
2058
- case RustSdkCryptoJs.DecryptionErrorCode.UnsignedSenderDevice:
2059
- // We're refusing to decrypt due to not trusting the sender,
2060
- // rather than failing to decrypt due to lack of keys, so we
2061
- // don't need to keep it on the pending list.
2062
- this.removeEventFromPendingList(event);
2063
- throw new DecryptionError(
2064
- DecryptionFailureCode.UNSIGNED_SENDER_DEVICE,
2065
- "The sender identity is not cross-signed.",
2066
- );
2067
-
2068
- // We don't map MismatchedIdentityKeys for now, as there is no equivalent in legacy.
2069
- // Just put it on the `UNKNOWN_ERROR` bucket.
2070
- default:
2071
- throw new DecryptionError(DecryptionFailureCode.UNKNOWN_ERROR, err.description, errorDetails);
2072
- }
2073
- }
2074
-
2075
- public async getEncryptionInfoForEvent(event: MatrixEvent): Promise<EventEncryptionInfo | null> {
2076
- if (!event.getClearContent() || event.isDecryptionFailure()) {
2077
- // not successfully decrypted
2078
- return null;
2079
- }
2080
-
2081
- // special-case outgoing events, which the rust crypto-sdk will barf on
2082
- if (event.status !== null) {
2083
- return { shieldColour: EventShieldColour.NONE, shieldReason: null };
2084
- }
2085
-
2086
- const encryptionInfo = await this.olmMachine.getRoomEventEncryptionInfo(
2087
- stringifyEvent(event),
2088
- new RustSdkCryptoJs.RoomId(event.getRoomId()!),
2089
- );
2090
-
2091
- return rustEncryptionInfoToJsEncryptionInfo(this.logger, encryptionInfo);
2092
- }
2093
-
2094
- /**
2095
- * Look for events which are waiting for a given megolm session
2096
- *
2097
- * Returns a list of events which were encrypted by `session` and could not be decrypted
2098
- */
2099
- public getEventsPendingRoomKey(roomId: string, sessionId: string): MatrixEvent[] {
2100
- const roomPendingEvents = this.eventsPendingKey.get(roomId);
2101
- if (!roomPendingEvents) return [];
2102
-
2103
- const sessionPendingEvents = roomPendingEvents.get(sessionId);
2104
- if (!sessionPendingEvents) return [];
2105
-
2106
- return [...sessionPendingEvents];
2107
- }
2108
-
2109
- /**
2110
- * Add an event to the list of those awaiting their session keys.
2111
- */
2112
- private addEventToPendingList(event: MatrixEvent): void {
2113
- const roomId = event.getRoomId();
2114
- // We shouldn't have events without a room id here.
2115
- if (!roomId) return;
2116
-
2117
- const roomPendingEvents = this.eventsPendingKey.getOrCreate(roomId);
2118
- const sessionPendingEvents = roomPendingEvents.getOrCreate(event.getWireContent().session_id);
2119
- sessionPendingEvents.add(event);
2120
- }
2121
-
2122
- /**
2123
- * Remove an event from the list of those awaiting their session keys.
2124
- */
2125
- private removeEventFromPendingList(event: MatrixEvent): void {
2126
- const roomId = event.getRoomId();
2127
- if (!roomId) return;
2128
-
2129
- const roomPendingEvents = this.eventsPendingKey.getOrCreate(roomId);
2130
- if (!roomPendingEvents) return;
2131
-
2132
- const sessionPendingEvents = roomPendingEvents.get(event.getWireContent().session_id);
2133
- if (!sessionPendingEvents) return;
2134
-
2135
- sessionPendingEvents.delete(event);
2136
-
2137
- // also clean up the higher-level maps if they are now empty
2138
- if (sessionPendingEvents.size === 0) {
2139
- roomPendingEvents.delete(event.getWireContent().session_id);
2140
- if (roomPendingEvents.size === 0) {
2141
- this.eventsPendingKey.delete(roomId);
2142
- }
2143
- }
2144
- }
2145
- }
2146
-
2147
- function stringifyEvent(event: MatrixEvent): string {
2148
- return JSON.stringify({
2149
- event_id: event.getId(),
2150
- type: event.getWireType(),
2151
- sender: event.getSender(),
2152
- state_key: event.getStateKey(),
2153
- content: event.getWireContent(),
2154
- origin_server_ts: event.getTs(),
2155
- });
2156
- }
2157
-
2158
- function rustEncryptionInfoToJsEncryptionInfo(
2159
- logger: Logger,
2160
- encryptionInfo: RustSdkCryptoJs.EncryptionInfo | undefined,
2161
- ): EventEncryptionInfo | null {
2162
- if (encryptionInfo === undefined) {
2163
- // not decrypted here
2164
- return null;
2165
- }
2166
-
2167
- // TODO: use strict shield semantics.
2168
- const shieldState = encryptionInfo.shieldState(false);
2169
-
2170
- let shieldColour: EventShieldColour;
2171
- switch (shieldState.color) {
2172
- case RustSdkCryptoJs.ShieldColor.Grey:
2173
- shieldColour = EventShieldColour.GREY;
2174
- break;
2175
- case RustSdkCryptoJs.ShieldColor.None:
2176
- shieldColour = EventShieldColour.NONE;
2177
- break;
2178
- default:
2179
- shieldColour = EventShieldColour.RED;
2180
- }
2181
-
2182
- let shieldReason: EventShieldReason | null;
2183
- if (shieldState.message === undefined) {
2184
- shieldReason = null;
2185
- } else if (shieldState.message === "Encrypted by an unverified user.") {
2186
- // this case isn't actually used with lax shield semantics.
2187
- shieldReason = EventShieldReason.UNVERIFIED_IDENTITY;
2188
- } else if (shieldState.message === "Encrypted by a device not verified by its owner.") {
2189
- shieldReason = EventShieldReason.UNSIGNED_DEVICE;
2190
- } else if (
2191
- shieldState.message === "The authenticity of this encrypted message can't be guaranteed on this device."
2192
- ) {
2193
- shieldReason = EventShieldReason.AUTHENTICITY_NOT_GUARANTEED;
2194
- } else if (shieldState.message === "Encrypted by an unknown or deleted device.") {
2195
- shieldReason = EventShieldReason.UNKNOWN_DEVICE;
2196
- } else {
2197
- logger.warn(`Unknown shield state message '${shieldState.message}'`);
2198
- shieldReason = EventShieldReason.UNKNOWN;
2199
- }
2200
-
2201
- return { shieldColour, shieldReason };
2202
- }
2203
-
2204
- type CryptoEvents = (typeof CryptoEvent)[keyof typeof CryptoEvent];
2205
- type RustCryptoEvents = Exclude<CryptoEvents, CryptoEvent.LegacyCryptoStoreMigrationProgress>;