feat(crypto-nodejs): Add store_path and store_passphrase to the OlmMachine constructor

feat(crypto-nodejs): Add `store_path` and `store_passphrase` to the `OlmMachine` constructor
This commit is contained in:
Ivan Enderlin
2022-06-15 07:28:29 +02:00
committed by GitHub
6 changed files with 79 additions and 19 deletions

View File

@@ -128,9 +128,9 @@ jobs:
strategy:
fail-fast: true
matrix:
node-version: [12.17, 14.0, 15.0, 16.0]
node-version: [14.0, 16.0, 18.0]
include:
- node-version: 16.0
- node-version: 18.0
build-doc: true
steps:

View File

@@ -27,12 +27,14 @@ tracing = ["tracing-subscriber"]
[dependencies]
matrix-sdk-crypto = { version = "0.5.0", path = "../matrix-sdk-crypto" }
matrix-sdk-common = { version = "0.5.0", path = "../matrix-sdk-common" }
matrix-sdk-sled = { version = "0.1.0", path = "../matrix-sdk-sled", default-features = false, features = ["crypto-store"] }
ruma = { version = "0.6.2", features = ["client-api-c", "rand", "unstable-msc2676", "unstable-msc2677"] }
vodozemac = { git = "https://github.com/matrix-org/vodozemac/", rev = "d0e744287a14319c2a9148fef3747548c740fc36" }
napi = { git = "https://github.com/Hywan/napi-rs", branch = "feat-either-n-up-to-26", default-features = false, features = ["napi6", "tokio_rt"] }
napi-derive = { git = "https://github.com/Hywan/napi-rs", branch = "feat-either-n-up-to-26" }
serde_json = "1.0.79"
http = "0.2.6"
zeroize = "1.3.0"
tracing-subscriber = { version = "0.3", default-features = false, features = ["tracing-log", "time", "smallvec", "fmt", "env-filter"], optional = true }
[build-dependencies]

View File

@@ -18,11 +18,14 @@ pretty classical by using [npm], see [the Downloading and installing
Node.js and npm
Page](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).
The binding is using NAPI 6 (Node API version 6), which means that is
compatible with Node.js versions 12.17.0, 14.0.0, 15.0.0 and 16.0.0
(see [the full Node API version
matrix](https://nodejs.org/api/n-api.html#node-api-version-matrix))
(we do not support the version 10.20).
The binding is compatible with, and tested against, the Node.js
versions that are in “current”, “active” or “maintenance” states,
according to [the Node.js Releases
Page](https://nodejs.org/en/about/releases/), _and_ which are
compatible with [NAPI v6 (Node.js
API)](https://nodejs.org/api/n-api.html#node-api-version-matrix). It
means that this binding will work with the following versions: 14.0.0,
16.0.0 and 18.0.0.
Once the Rust compiler, Node.js and npm are installed, you can run the
following commands:

View File

@@ -18,7 +18,7 @@
"typedoc": "^0.22.17"
},
"engines": {
"node": ">= 10"
"node": ">= 14"
},
"scripts": {
"build": "napi build --platform --release --strip",

View File

@@ -1,6 +1,9 @@
//! The crypto specific Olm objects.
use std::collections::{BTreeMap, HashMap};
use std::{
collections::{BTreeMap, HashMap},
sync::Arc,
};
use napi::bindgen_prelude::Either7;
use napi_derive::*;
@@ -9,6 +12,7 @@ use ruma::{
OwnedTransactionId, UInt,
};
use serde_json::Value as JsonValue;
use zeroize::Zeroize;
use crate::{
encryption, identifiers, into_err, requests, responses, responses::response_from_string,
@@ -37,25 +41,59 @@ impl OlmMachine {
/// Create a new memory-based `OlmMachine` asynchronously.
///
/// The created machine will keep the encryption keys only in
/// memory and once the object is dropped the keys will be lost.
/// The persistence of the encryption keys and all the inner
/// objects are controlled by the `store_path` argument.
///
/// # Arguments
///
/// * `user_id`, the unique ID of the user that owns this machine.
/// * `device_id`, the unique id of the device that owns this machine.
/// * `store_path`, the path to a directory where the state of the machine
/// should be persisted; if not set, the created machine will keep the
/// encryption keys only in memory, and once the object is dropped, the
/// keys will be lost.
/// * `store_passphrase`, the passphrase that should be used to encrypt the
/// data at rest in the store. **Warning**, if no passphrase is given, the
/// store and all its data will remain unencrypted. This argument is
/// ignored if `store_path` is not set.
#[napi]
pub async fn initialize(
user_id: &identifiers::UserId,
device_id: &identifiers::DeviceId,
) -> Self {
OlmMachine {
inner: matrix_sdk_crypto::OlmMachine::new(
user_id.inner.as_ref(),
device_id.inner.as_ref(),
)
.await,
}
store_path: Option<String>,
mut store_passphrase: Option<String>,
) -> napi::Result<OlmMachine> {
let store = store_path
.map(|store_path| {
matrix_sdk_sled::CryptoStore::open_with_passphrase(
store_path,
store_passphrase.as_deref(),
)
.map(Arc::new)
.map_err(into_err)
})
.transpose()?;
store_passphrase.zeroize();
Ok(OlmMachine {
inner: match store {
Some(store) => matrix_sdk_crypto::OlmMachine::with_store(
user_id.inner.as_ref(),
device_id.inner.as_ref(),
store,
)
.await
.map_err(into_err)?,
None => {
matrix_sdk_crypto::OlmMachine::new(
user_id.inner.as_ref(),
device_id.inner.as_ref(),
)
.await
}
},
})
}
/// It's not possible to construct an `OlmMachine` with its

View File

@@ -1,4 +1,7 @@
const { OlmMachine, UserId, DeviceId, RoomId, DeviceLists, RequestType, KeysUploadRequest, KeysQueryRequest, KeysClaimRequest, EncryptionSettings, DecryptedRoomEvent, VerificationState } = require('../');
const path = require('path');
const os = require('os');
const fs = require('fs/promises');
describe(OlmMachine.name, () => {
test('cannot be instantiated with the constructor', () => {
@@ -9,6 +12,20 @@ describe(OlmMachine.name, () => {
expect(await OlmMachine.initialize(new UserId('@foo:bar.org'), new DeviceId('baz'))).toBeInstanceOf(OlmMachine);
});
describe('can be instantiated with a store', () => {
test('with no passphrase', async () => {
const temp_directory = await fs.mkdtemp(path.join(os.tmpdir(), 'matrix-sdk-crypto--'));
expect(await OlmMachine.initialize(new UserId('@foo:bar.org'), new DeviceId('baz'), temp_directory)).toBeInstanceOf(OlmMachine);
});
test('with a passphrase', async () => {
const temp_directory = await fs.mkdtemp(path.join(os.tmpdir(), 'matrix-sdk-crypto--'));
expect(await OlmMachine.initialize(new UserId('@foo:bar.org'), new DeviceId('baz'), temp_directory, 'hello')).toBeInstanceOf(OlmMachine);
});
});
const user = new UserId('@alice:example.org');
const device = new DeviceId('foobar');
const room = new RoomId('!baz:matrix.org');