From 7f07ac52ef8d4e577a847bcf089ee8099adfef0c Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Tue, 23 Aug 2022 15:00:33 +0200 Subject: [PATCH] feat(crypto-js): Add store configuration to the `OlmMachine` constructor. The `OlmMachine` constructor now has 2 more optional arguments: `store_name` and `store_passphrase`, to use Indexed DB as the backend to store the Olm machine keys, rather than having an in-memory Olm machine. Node.js is used to test our binding. Indexed DB is absent of Node.js. So, firstly, we are using the `fake-indexeddb` JavaScript library to mimic the same API inside Node.js. And, secondly, we use our own fork of the `indexed_db_futures` Rust crate to provide add support for Node.js too ([PR is here](https://github.com/Alorel/rust-indexed-db/pull/11)). It basically looks in the Node.js global environment if the `indexedDB` getter is present, just like it is already done for `Window` on any browser, or `WorkerGlobalScope` for workers. --- Cargo.lock | 5 ++- bindings/matrix-sdk-crypto-js/Cargo.toml | 2 + bindings/matrix-sdk-crypto-js/package.json | 3 +- bindings/matrix-sdk-crypto-js/src/machine.rs | 44 +++++++++++++++++-- .../tests/machine.test.js | 8 ++++ crates/matrix-sdk-indexeddb/Cargo.toml | 2 +- 6 files changed, 57 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b9692d7b..5916b35fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1931,8 +1931,7 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexed_db_futures" version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26ac735f676c52305becf53264b91cea9866a8de61ccbf464405b377b9cbca9" +source = "git+https://github.com/Hywan/rust-indexed-db?branch=feat-factory-nodejs#5dab67890cea0ab88b967031adc09179a537d77c" dependencies = [ "cfg-if", "js-sys", @@ -2365,6 +2364,7 @@ dependencies = [ "js-sys", "matrix-sdk-common", "matrix-sdk-crypto", + "matrix-sdk-indexeddb", "ruma", "serde_json", "tracing", @@ -2372,6 +2372,7 @@ dependencies = [ "vodozemac", "wasm-bindgen", "wasm-bindgen-futures", + "zeroize", ] [[package]] diff --git a/bindings/matrix-sdk-crypto-js/Cargo.toml b/bindings/matrix-sdk-crypto-js/Cargo.toml index fa86ac7d2..a75349b79 100644 --- a/bindings/matrix-sdk-crypto-js/Cargo.toml +++ b/bindings/matrix-sdk-crypto-js/Cargo.toml @@ -28,6 +28,7 @@ tracing = [] [dependencies] matrix-sdk-common = { version = "0.5.0", path = "../../crates/matrix-sdk-common" } matrix-sdk-crypto = { version = "0.5.0", path = "../../crates/matrix-sdk-crypto" } +matrix-sdk-indexeddb = { version = "0.1.0", path = "../../crates/matrix-sdk-indexeddb" } ruma = { git = "https://github.com/ruma/ruma", rev = "173eb15147c904d7dc0ee894de6114743926e33e", features = ["client-api-c", "js", "rand", "unstable-msc2676", "unstable-msc2677"] } wasm-bindgen = "0.2.80" wasm-bindgen-futures = "0.4.30" @@ -38,6 +39,7 @@ http = "0.2.6" anyhow = "1.0.58" tracing = { version = "0.1.35", default-features = false, features = ["attributes"] } tracing-subscriber = { version = "0.3.14", default-features = false, features = ["registry", "std"] } +zeroize = "1.3.0" [dependencies.vodozemac] git = "https://github.com/matrix-org/vodozemac/" diff --git a/bindings/matrix-sdk-crypto-js/package.json b/bindings/matrix-sdk-crypto-js/package.json index 59cce9d60..8de6990e5 100644 --- a/bindings/matrix-sdk-crypto-js/package.json +++ b/bindings/matrix-sdk-crypto-js/package.json @@ -30,7 +30,8 @@ "jest": "^28.1.0", "typedoc": "^0.22.17", "cross-env": "^7.0.3", - "yargs-parser": "~21.0.1" + "yargs-parser": "~21.0.1", + "fake-indexeddb": "^4.0" }, "engines": { "node": ">= 10" diff --git a/bindings/matrix-sdk-crypto-js/src/machine.rs b/bindings/matrix-sdk-crypto-js/src/machine.rs index d5be9449b..bdc3f9755 100644 --- a/bindings/matrix-sdk-crypto-js/src/machine.rs +++ b/bindings/matrix-sdk-crypto-js/src/machine.rs @@ -1,11 +1,13 @@ //! The crypto specific Olm objects. use std::collections::BTreeMap; +use std::sync::Arc; use js_sys::{Array, Map, Promise, Set}; use ruma::{serde::Raw, DeviceKeyAlgorithm, OwnedTransactionId, UInt}; use serde_json::Value as JsonValue; use wasm_bindgen::prelude::*; +use zeroize::Zeroize; use crate::{ downcast, encryption, @@ -36,14 +38,50 @@ impl OlmMachine { /// that owns this machine. #[wasm_bindgen(constructor)] #[allow(clippy::new_ret_no_self)] - pub fn new(user_id: &identifiers::UserId, device_id: &identifiers::DeviceId) -> Promise { + pub fn new( + user_id: &identifiers::UserId, + device_id: &identifiers::DeviceId, + store_name: Option, + store_passphrase: Option, + ) -> Promise { let user_id = user_id.inner.clone(); let device_id = device_id.inner.clone(); future_to_promise(async move { + let store = match (store_name, store_passphrase) { + (Some(store_name), Some(mut store_passphrase)) => { + let store = Some( + matrix_sdk_indexeddb::IndexeddbCryptoStore::open_with_passphrase( + &store_name, + &store_passphrase, + ) + .await + .map(Arc::new)?, + ); + + store_passphrase.zeroize(); + + store + } + + _ => None, + }; + Ok(OlmMachine { - inner: matrix_sdk_crypto::OlmMachine::new(user_id.as_ref(), device_id.as_ref()) - .await, + inner: match store { + Some(store) => { + matrix_sdk_crypto::OlmMachine::with_store( + user_id.as_ref(), + device_id.as_ref(), + store, + ) + .await? + } + None => { + matrix_sdk_crypto::OlmMachine::new(user_id.as_ref(), device_id.as_ref()) + .await + } + }, }) }) } diff --git a/bindings/matrix-sdk-crypto-js/tests/machine.test.js b/bindings/matrix-sdk-crypto-js/tests/machine.test.js index d4e35641a..4d5291dc0 100644 --- a/bindings/matrix-sdk-crypto-js/tests/machine.test.js +++ b/bindings/matrix-sdk-crypto-js/tests/machine.test.js @@ -1,10 +1,18 @@ const { OlmMachine, UserId, DeviceId, RoomId, DeviceLists, RequestType, KeysUploadRequest, KeysQueryRequest, KeysClaimRequest, EncryptionSettings, DecryptedRoomEvent, VerificationState } = require('../pkg/matrix_sdk_crypto_js'); +require('fake-indexeddb/auto'); describe(OlmMachine.name, () => { test('can be instantiated with the async initializer', async () => { expect(await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'))).toBeInstanceOf(OlmMachine); }); + test('can be instantiated with a store', async () => { + let store_name = 'hello'; + let store_passphrase = 'world'; + + expect(await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase)).toBeInstanceOf(OlmMachine); + }); + const user = new UserId('@alice:example.org'); const device = new DeviceId('foobar'); const room = new RoomId('!baz:matrix.org'); diff --git a/crates/matrix-sdk-indexeddb/Cargo.toml b/crates/matrix-sdk-indexeddb/Cargo.toml index 259af8c5c..79f33a924 100644 --- a/crates/matrix-sdk-indexeddb/Cargo.toml +++ b/crates/matrix-sdk-indexeddb/Cargo.toml @@ -26,7 +26,7 @@ base64 = "0.13.0" dashmap = { version = "5.2.0", optional = true } derive_builder = "0.11.2" futures-util = { version = " 0.3.21", default-features = false, features = ["alloc"], optional = true } -indexed_db_futures = "0.2.3" +indexed_db_futures = { git = "https://github.com/Hywan/rust-indexed-db", branch = "feat-factory-nodejs" } js-sys = { version = "0.3.58" } matrix-sdk-base = { version = "0.5.0", path = "../matrix-sdk-base" } matrix-sdk-crypto = { version = "0.5.0", path = "../matrix-sdk-crypto", optional = true }