Skip to content

Fix backed-up keys being re-backed-up #121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# UNRELEASED

**BREAKING CHANGES**

- `OlmMachine.importBackedUpRoomKeys` now takes a `backupVersion` argument.

**Other changes**

- Update matrix-rust-sdk to `7e44fbca7`, which includes:

- Avoid emitting entries from `identities_stream_raw` and `devices_stream` when
we receive a `/keys/query` response which shows that no devices changed.
([#3442](https://github.com/matrix-org/matrix-rust-sdk/pull/3442)).

- Fix to a bug introduced in matrix-sdk-crypto-wasm v4.10.0 which caused
keys that had been imported from key backup to be backed up again, when
using the in-memory datastore.

# matrix-sdk-crypto-wasm v4.10.0

- Expose new constructor function `OlmMachine.openWithKey()`.
Expand All @@ -19,7 +35,7 @@
- Add a constructor for the `Curve25519PublicKey` type. This allows us to
create a `Curve25519PublicKey` from a Base64 string on the Javascript side.

- Update matrix-rust-sdk to `7a887766c`, which includes:
- Update matrix-rust-sdk to `d7a887766c`, which includes:

- Add data types to parse the QR code data for the QR code login defined in
[MSC4108](https://github.com/matrix-org/matrix-spec-proposals/pull/4108)
Expand Down
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use matrix_sdk_common::ruma::{
};
use matrix_sdk_crypto::{
backups::MegolmV1BackupKey,
olm::BackedUpRoomKey,
olm::{BackedUpRoomKey, ExportedRoomKey},
store::{DeviceChanges, IdentityChanges},
types::RoomKeyBackupInfo,
CryptoStoreError, EncryptionSyncChanges, GossippedSecret,
Expand Down Expand Up @@ -1052,11 +1052,12 @@ impl OlmMachine {
&self,
backed_up_room_keys: &Map,
progress_listener: Option<Function>,
backup_version: String,
) -> Result<Promise, JsValue> {
let me = self.inner.clone();

// convert the js-side data into rust data
let mut keys: BTreeMap<_, BTreeMap<_, _>> = BTreeMap::new();
let mut keys = Vec::new();
let mut failures = 0;
for backed_up_room_keys_entry in backed_up_room_keys.entries() {
let backed_up_room_keys_entry: Array = backed_up_room_keys_entry?.dyn_into()?;
Expand All @@ -1071,7 +1072,11 @@ impl OlmMachine {
if let Ok(key) =
serde_wasm_bindgen::from_value::<BackedUpRoomKey>(room_room_keys_entry.get(1))
{
keys.entry(room_id.clone()).or_default().insert(session_id.into(), key);
keys.push(ExportedRoomKey::from_backed_up_room_key(
room_id.clone(),
session_id.into(),
key,
));
} else {
failures += 1;
}
Expand All @@ -1080,8 +1085,8 @@ impl OlmMachine {

Ok(future_to_promise(async move {
let result: RoomKeyImportResult = me
.backup_machine()
.import_backed_up_room_keys(keys, |progress, total_valid| {
.store()
.import_room_keys(keys, Some(&backup_version), |progress, total_valid| {
if let Some(callback) = &progress_listener {
callback
.call3(
Expand Down
27 changes: 16 additions & 11 deletions tests/machine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1257,7 +1257,7 @@ describe(OlmMachine.name, () => {
const progressListener = jest.fn();
const m2 = await machine();
await m2.saveBackupDecryptionKey(keyBackupKey, "1");
const result = await m2.importBackedUpRoomKeys(decryptedKeyMap, progressListener);
const result = await m2.importBackedUpRoomKeys(decryptedKeyMap, progressListener, "1");
expect(result.importedCount).toStrictEqual(1);
expect(result.totalCount).toStrictEqual(1);
expect(result.keys()).toMatchObject(
Expand Down Expand Up @@ -1442,27 +1442,32 @@ describe(OlmMachine.name, () => {
test("Updating devices should call devicesUpdatedCallback", async () => {
const userId = new UserId("@alice:example.org");
const deviceId = new DeviceId("ABCDEF");
const machine = await OlmMachine.initialize(userId, deviceId);
const firstMachine = await OlmMachine.initialize(userId, deviceId);

const callback = jest.fn().mockImplementation(() => Promise.resolve(undefined));
machine.registerDevicesUpdatedCallback(callback);
firstMachine.registerDevicesUpdatedCallback(callback);

const outgoingRequests = await machine.outgoingRequests();
const secondDeviceId = new DeviceId("GHIJKL");
const secondMachine = await OlmMachine.initialize(userId, secondDeviceId);

// Fish the KeysUploadRequest out of secondMachine's outgoingRequests.
let deviceKeys;
// outgoingRequests will have a KeysUploadRequest before the
// KeysQueryRequest, so we grab the device upload and put it in the
// response to the /keys/query
Comment on lines -1452 to -1454
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test didn't work any more after the rust-sdk upgrade, due to matrix-org/matrix-rust-sdk#3442: the response no longer triggered a device update notification. Hence, we now feed the device from a second OlmMachine in.

for (const request of outgoingRequests) {
for (const request of await secondMachine.outgoingRequests()) {
if (request instanceof KeysUploadRequest) {
deviceKeys = JSON.parse(request.body).device_keys;
} else if (request instanceof KeysQueryRequest) {
await machine.markRequestAsSent(
}
}

// ... and feed it into firstMachine's KeysQueryRequest
for (const request of await firstMachine.outgoingRequests()) {
if (request instanceof KeysQueryRequest) {
await firstMachine.markRequestAsSent(
request.id,
request.type,
JSON.stringify({
device_keys: {
"@alice:example.org": {
ABCDEF: deviceKeys,
GHIJKL: deviceKeys,
},
},
}),
Expand Down
Loading