feat(crypto-js): Add store configuration to the OlmMachine constructor

feat(crypto-js): Add store configuration to the `OlmMachine` constructor
This commit is contained in:
Ivan Enderlin
2022-08-25 11:37:45 +02:00
committed by GitHub
6 changed files with 128 additions and 7 deletions
Generated
+3 -2
View File
@@ -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]]
+2
View File
@@ -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/"
+2 -1
View File
@@ -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"
+61 -3
View File
@@ -34,16 +34,74 @@ impl OlmMachine {
/// `user_id` represents the unique ID of the user that owns this
/// machine. `device_id` represents the unique ID of the device
/// that owns this machine.
///
/// `store_name` and `store_passphrase` are both optional, but
/// must be both set to have an effect. If they are both set, the
/// state of the machine will persist in a database named
/// `store_name` where its content is encrypted by the passphrase
/// given by `store_passphrase`. If they are not both set, the
/// created machine will keep the encryption keys only in memory,
/// and once the object is dropped, the keys will be lost.
#[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<String>,
store_passphrase: Option<String>,
) -> 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) {
// We need this `#[cfg]` because `IndexeddbCryptoStore`
// implements `CryptoStore` only on `target_arch =
// "wasm32"`. Without that, we could have a compilation
// error when checking the entire workspace. In
// practise, it doesn't impact this crate because it's
// always compiled for `wasm32`.
#[cfg(target_arch = "wasm32")]
(Some(store_name), Some(mut store_passphrase)) => {
use std::sync::Arc;
use zeroize::Zeroize;
let store = Some(
matrix_sdk_indexeddb::IndexeddbCryptoStore::open_with_passphrase(
&store_name,
&store_passphrase,
)
.await
.map(Arc::new)?,
);
store_passphrase.zeroize();
store
}
(Some(_), None) => return Err(anyhow::Error::msg("The `store_name` has been set, and so, it expects a `store_passphrase`, which is not set; please provide one")),
(None, Some(_)) => return Err(anyhow::Error::msg("The `store_passphrase` has been set, but it has an effect only if `store_name` is set, which is not; please provide one")),
_ => 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
}
},
})
})
}
@@ -1,10 +1,69 @@
const { OlmMachine, UserId, DeviceId, DeviceKeyId, RoomId, DeviceLists, RequestType, KeysUploadRequest, KeysQueryRequest, KeysClaimRequest, EncryptionSettings, DecryptedRoomEvent, VerificationState, CrossSigningStatus, MaybeSignature } = 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 () => {
// No databases.
expect(await indexedDB.databases()).toHaveLength(0);
let store_name = 'hello';
let store_passphrase = 'world';
// Creating a new Olm machine.
expect(await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase)).toBeInstanceOf(OlmMachine);
// Oh, there is 2 databases now, prefixed by `store_name`.
let databases = await indexedDB.databases();
expect(databases).toHaveLength(2);
expect(databases).toStrictEqual([
{ name: `${store_name}::matrix-sdk-crypto-meta`, version: 1 },
{ name: `${store_name}::matrix-sdk-crypto`, version: 1 },
]);
// Creating a new Olm machine, with the stored state.
expect(await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase)).toBeInstanceOf(OlmMachine);
// Same number of databases.
expect(await indexedDB.databases()).toHaveLength(2);
});
describe('cannot be instantiated with a store', () => {
test('store name is missing', async () => {
let store_name = null;
let store_passphrase = 'world';
let err = null;
try {
await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase);
} catch (error) {
err = error;
}
expect(err).toBeDefined();
});
test('store passphrase is missing', async () => {
let store_name = 'hello';
let store_passphrase = null;
let err = null;
try {
await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase);
} catch (error) {
err = error;
}
expect(err).toBeDefined();
});
});
const user = new UserId('@alice:example.org');
const device = new DeviceId('foobar');
const room = new RoomId('!baz:matrix.org');
+1 -1
View File
@@ -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 }