Skip to content

Commit 9cbd897

Browse files
committed
Support ProcessedToDeviceEvent variants returned by receiveSyncChanges
1 parent 3f74785 commit 9cbd897

File tree

8 files changed

+190
-43
lines changed

8 files changed

+190
-43
lines changed

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
# UNRELEASED
22

3+
- Update matrix-rusk-sdk to `35a2ce9`, which includes:
4+
5+
- Add variants for plain text and encrypted to-device events ([#4935](https://github.com/matrix-org/matrix-rust-sdk/pull/4935))
6+
7+
- **BREAKING**: `OlmMachine.receiveSyncChanges` now returns a list of
8+
`ProcessedToDeviceEvent` instead of a json encoded list of json encoded events.
9+
This allows to make the difference between an event that was sent in clear and
10+
the same event successfully decrypted.
11+
312
# matrix-sdk-crypto-wasm v14.1.0
413

5-
- Update matrix-rusk-sdk to `0.11.0`, which includees:
14+
- Update matrix-rusk-sdk to `0.11.0`, which includes:
615

716
- Add support for the shared history flag defined in
817
[MSC3061](https://github.com/matrix-org/matrix-spec-proposals/pull/3061).

Cargo.lock

Lines changed: 5 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ futures-util = "0.3.27"
6565
getrandom = { version = "0.3.0", features = ["wasm_js"] }
6666
http = "1.1.0"
6767
js-sys = "0.3.49"
68-
matrix-sdk-common = { version = "0.11.0", features = ["js"] }
69-
matrix-sdk-indexeddb = { version = "0.11.0", default-features = false, features = ["e2e-encryption"] }
70-
matrix-sdk-qrcode = { version = "0.11.0", optional = true }
68+
matrix-sdk-common = { git = "https://github.com/matrix-org/matrix-rust-sdk", rev = "35a2ce97d84af8cea6b9e1850a8ff4ff5c66d712", features = ["js"] }
69+
matrix-sdk-indexeddb = { git = "https://github.com/matrix-org/matrix-rust-sdk", rev = "35a2ce97d84af8cea6b9e1850a8ff4ff5c66d712", default-features = false, features = ["e2e-encryption"] }
70+
matrix-sdk-qrcode = { git = "https://github.com/matrix-org/matrix-rust-sdk", rev = "35a2ce97d84af8cea6b9e1850a8ff4ff5c66d712", optional = true }
7171
serde = "1.0.91"
7272
serde_json = "1.0.91"
7373
serde-wasm-bindgen = "0.6.5"
@@ -83,7 +83,8 @@ wasm-bindgen-test = "0.3.37"
8383
vergen-gitcl = { version = "1.0.0", features = ["build"] }
8484

8585
[dependencies.matrix-sdk-crypto]
86-
version = "0.11.0"
86+
git = "https://github.com/matrix-org/matrix-rust-sdk"
87+
rev = "35a2ce97d84af8cea6b9e1850a8ff4ff5c66d712"
8788
default-features = false
8889
features = ["js", "automatic-room-key-forwarding"]
8990

index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ declare module "./pkg/matrix_sdk_crypto_wasm.js" {
6969
changed_devices: DeviceLists,
7070
one_time_keys_counts: Map<string, number>,
7171
unused_fallback_keys?: Set<string> | null,
72-
): Promise<string>;
72+
): Promise<Array<ProcessedToDeviceEvent>>;
7373
outgoingRequests(): Promise<Array<OutgoingRequest>>;
7474
markRequestAsSent(request_id: string, request_type: RequestType, response: string): Promise<boolean>;
7575
encryptRoomEvent(room_id: RoomId, event_type: string, content: string): Promise<string>;

src/machine.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use crate::{
4545
types::{self, RoomKeyImportResult, RoomSettings, SignatureVerification},
4646
verification, vodozemac,
4747
};
48+
use crate::types::ProcessedToDeviceEvent;
4849

4950
/// State machine implementation of the Olm/Megolm encryption protocol
5051
/// used for Matrix end to end encryption.
@@ -298,7 +299,7 @@ impl OlmMachine {
298299
///
299300
/// # Returns
300301
///
301-
/// A list of JSON strings, containing the decrypted to-device events.
302+
/// A list of {@link ProcessedToDeviceEvent} object, containing the serialized processed event and if it was successfully decrypted, sent in clear, unable to decrypt or invalid.
302303
#[wasm_bindgen(js_name = "receiveSyncChanges")]
303304
pub fn receive_sync_changes(
304305
&self,
@@ -341,7 +342,7 @@ impl OlmMachine {
341342
// we discard the list of updated room keys in the result; JS applications are
342343
// expected to use register_room_key_updated_callback to receive updated room
343344
// keys.
344-
let (decrypted_to_device_events, _) = me
345+
let (processed_to_device_events, _) = me
345346
.receive_sync_changes(EncryptionSyncChanges {
346347
to_device_events,
347348
changed_devices: &changed_devices,
@@ -353,7 +354,11 @@ impl OlmMachine {
353354
})
354355
.await?;
355356

356-
Ok(serde_json::to_string(&decrypted_to_device_events)?)
357+
let processed_to_device_events: Vec<ProcessedToDeviceEvent> = processed_to_device_events
358+
.into_iter()
359+
.map(ProcessedToDeviceEvent::from)
360+
.collect();
361+
Ok(processed_to_device_events)
357362
}))
358363
}
359364

src/types.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,71 @@ impl From<&RoomSettings> for matrix_sdk_crypto::store::RoomSettings {
362362
}
363363
}
364364
}
365+
366+
367+
/// Represent the type of {@link ProcessedToDeviceEvent}.
368+
#[wasm_bindgen]
369+
#[derive(Debug, Clone)]
370+
pub enum ProcessedToDeviceEventType {
371+
/// A successfully-decrypted encrypted event.
372+
Decrypted,
373+
374+
/// An encrypted event which could not be decrypted.
375+
UnableToDecrypt,
376+
377+
/// An unencrypted event (sent in clear).
378+
PlainText,
379+
380+
/// An invalid to device event that was ignored because it is missing some
381+
/// required information to be processed (like no event `type` for
382+
/// example)
383+
Invalid
384+
}
385+
386+
387+
/// Represent a ToDevice event after it has been processed by {@link OlmMachine#receiveSyncChanges}.
388+
///
389+
#[wasm_bindgen(getter_with_clone)]
390+
#[derive(Debug, Clone)]
391+
pub struct ProcessedToDeviceEvent {
392+
393+
/// The type of processed event
394+
#[wasm_bindgen(getter_with_clone, js_name = "type")]
395+
pub processed_type: ProcessedToDeviceEventType,
396+
397+
/// A JSON-encoded string containing the processed event.
398+
/// For the `Decrypted` type this will be the decrypted event as if it was sent in clear (For room keys or secrets some part of the content might have been zeroize'd).
399+
#[wasm_bindgen(readonly, js_name = "wireEvent")]
400+
pub wire_event: JsString,
401+
}
402+
403+
impl From<matrix_sdk_crypto::types::ProcessedToDeviceEvent> for ProcessedToDeviceEvent {
404+
fn from(value: matrix_sdk_crypto::types::ProcessedToDeviceEvent) -> Self {
405+
match value {
406+
matrix_sdk_crypto::types::ProcessedToDeviceEvent::Decrypted(decrypted_event) => {
407+
ProcessedToDeviceEvent {
408+
processed_type: ProcessedToDeviceEventType::Decrypted,
409+
wire_event: decrypted_event.json().get().to_owned().into(),
410+
}
411+
}
412+
matrix_sdk_crypto::types::ProcessedToDeviceEvent::UnableToDecrypt(utd) => {
413+
ProcessedToDeviceEvent {
414+
processed_type: ProcessedToDeviceEventType::UnableToDecrypt,
415+
wire_event: utd.json().get().to_owned().into(),
416+
}
417+
}
418+
matrix_sdk_crypto::types::ProcessedToDeviceEvent::PlainText(plain) => {
419+
ProcessedToDeviceEvent {
420+
processed_type: ProcessedToDeviceEventType::PlainText,
421+
wire_event: plain.json().get().to_owned().into(),
422+
}
423+
}
424+
matrix_sdk_crypto::types::ProcessedToDeviceEvent::Invalid(invalid) => {
425+
ProcessedToDeviceEvent {
426+
processed_type: ProcessedToDeviceEventType::Invalid,
427+
wire_event: invalid.json().get().to_owned().into(),
428+
}
429+
}
430+
}
431+
}
432+
}

tests/helper.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ async function addMachineToMachine(machineToAdd, machine) {
1616
const oneTimeKeyCounts = new Map();
1717
const unusedFallbackKeys = new Set();
1818

19-
const receiveSyncChanges = JSON.parse(
20-
await machineToAdd.receiveSyncChanges(toDeviceEvents, changedDevices, oneTimeKeyCounts, unusedFallbackKeys),
19+
const receiveSyncChanges = await machineToAdd.receiveSyncChanges(
20+
toDeviceEvents,
21+
changedDevices,
22+
oneTimeKeyCounts,
23+
unusedFallbackKeys,
2124
);
2225

2326
expect(receiveSyncChanges).toEqual([]);

tests/machine.test.ts

Lines changed: 88 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
MegolmDecryptionError,
2121
OlmMachine,
2222
OwnUserIdentity,
23+
ProcessedToDeviceEventType,
2324
RequestType,
2425
RoomId,
2526
RoomKeyWithheldInfo,
@@ -306,8 +307,11 @@ describe(OlmMachine.name, () => {
306307
const oneTimeKeyCounts = new Map();
307308
const unusedFallbackKeys = new Set();
308309

309-
const receiveSyncChanges = JSON.parse(
310-
await m.receiveSyncChanges(toDeviceEvents, changedDevices, oneTimeKeyCounts, unusedFallbackKeys),
310+
const receiveSyncChanges = await m.receiveSyncChanges(
311+
toDeviceEvents,
312+
changedDevices,
313+
oneTimeKeyCounts,
314+
unusedFallbackKeys,
311315
);
312316

313317
expect(receiveSyncChanges).toEqual([]);
@@ -319,8 +323,11 @@ describe(OlmMachine.name, () => {
319323
const changedDevices = new DeviceLists();
320324
const oneTimeKeyCounts = new Map();
321325

322-
const receiveSyncChanges = JSON.parse(
323-
await m.receiveSyncChanges(toDeviceEvents, changedDevices, oneTimeKeyCounts, undefined),
326+
const receiveSyncChanges = await m.receiveSyncChanges(
327+
toDeviceEvents,
328+
changedDevices,
329+
oneTimeKeyCounts,
330+
undefined,
324331
);
325332

326333
expect(receiveSyncChanges).toEqual([]);
@@ -333,8 +340,11 @@ describe(OlmMachine.name, () => {
333340
const oneTimeKeyCounts = new Map();
334341
const unusedFallbackKeys = new Set();
335342

336-
const receiveSyncChanges = JSON.parse(
337-
await m.receiveSyncChanges(toDeviceEvents, changedDevices, oneTimeKeyCounts, unusedFallbackKeys),
343+
const receiveSyncChanges = await m.receiveSyncChanges(
344+
toDeviceEvents,
345+
changedDevices,
346+
oneTimeKeyCounts,
347+
unusedFallbackKeys,
338348
);
339349

340350
expect(receiveSyncChanges).toEqual([]);
@@ -1629,11 +1639,11 @@ describe(OlmMachine.name, () => {
16291639
undefined,
16301640
);
16311641

1632-
const receivedToDevices = JSON.parse(received);
1633-
expect(receivedToDevices).toBeInstanceOf(Array);
1634-
const receivedToDeviceArray: Array<any> = receivedToDevices;
1635-
expect(receivedToDeviceArray.length).toBe(1);
1636-
const toDeviceEvent = receivedToDeviceArray[0];
1642+
expect(received.length).toBe(1);
1643+
const processed = received[0];
1644+
expect(processed.type).toEqual(ProcessedToDeviceEventType.PlainText);
1645+
1646+
let toDeviceEvent = JSON.parse(processed.wireEvent);
16371647

16381648
expect(toDeviceEvent.sender).toEqual("@alice:example.com");
16391649
expect(toDeviceEvent.type).toEqual("custom.type");
@@ -1649,7 +1659,7 @@ describe(OlmMachine.name, () => {
16491659
content: {
16501660
"algorithm": "m.olm.v1.curve25519-aes-sha2",
16511661
"ciphertext": {
1652-
aliceCurve: {
1662+
[aliceCurve]: {
16531663
// this payload is just captured from a sync of some other element web with other users
16541664
body: "Awogjvpx458CGhuo77HX/+tp1sxgRoCi7iAlzMvfrpbWoREQAiKACysX/p+ojr5QitCi9WRXNyamW2v2LTvoyWKtVaA2oHnYGR5s5RYhDfnIgh5MMSqqKlAbfqLvrbLovTYcKagCBbFnbA43f6zYM44buGgy8q70hMVH5WP6aK1E9Z3DVZ+8PnXQGpsrxvz2IsL6w0Nzl/qUyBEQFcgkjoDPawbsZRCllMgq2LQUyqlun6IgDTCozqsfxhDWpdfYGde4z16m34Ang7f5pH+BmPrFs6E1AO5+UbhhhS6NwWlfEtA6/9yfMxWLz1d2OrLh+QG7lYFAU9/CzIoPxaHKKr4JxgL9CjsmUPyDymWOWHP0jLi1NwpOv6hGpx0FgM7jJIMk6gWGgC5rEgEeTIwdrJh3F9OKTNSva5hvD9LomGk6tZgzQG6oap1e3wiOUyTt6S7BlyMppIu3RlIiNihZ9e17JEGiGDXOXzMJ6ISAgvGVgTP7+EvyEt2Wt4du7uBo/UvljRvVNu3I8tfItizPAOlvz460+aBDxk+sflJWt7OnhiyPnOCfopb+1RzqKVCnnPyVaP2f4BPf8qpn/f5YZk+5jJgBrGPiHzzmb3sQ5pC470s6+U3MpVFlFTG/xPBtMRMwPsbKoHfnRPqIqGu5dQ1Sw7T6taDXWjP450TvjxgHK5t2z1rLA2SXzAB1P8xbi6YXqQwxL6PvMNHn/TM0jiIQHYuqg5/RKLyhHybfP8JAjgNBw9z16wfKR/YoYFr7c+S4McQaMNa8v2SxGzhpCC3duAoK2qCWLEkYRO5cMCsGm/9bf8Q+//OykygBU/hdkT1eHUbexgALPLdfhzduutU7pbChg4T7SH7euh/3NLmS/SQvkmPfm3ckbh/Vlcj9CsXws/7MX/VJbhpbyzgBNtMnbG6tAeAofMa6Go/yMgiNBZIhLpAm31iUbUhaGm2IIlF/lsmSYEiBPoSVfFU44tetX2I/PBDGiBlzyU+yC2TOEBwMGxBE3WHbIe5/7sKW8xJF9t+HBfxIyW1QRtY3EKdEcuVOTyMxYzq3L5OKOOtPDHObYiiXg00mAgdQqgfkEAIfoRCOa2NYfTedwwo0S77eQ1sPvW5Hhf+Cm+bLibkWzaYHEZF+vyE9/Tn0tZGtH07RXfUyhp1vtTH49OBZHGkb/r+L8OjYJTST1dDCGqeGXO3uwYjoWHXtezLVHYgL+UOwcLJfMF5s9DQiqcfYXzp2kEWGsaetBFXcUWqq4RMHqlr6QfbxyuYLlQzc/AYA/MrT3J6nDpNLcvozH3RcIs8NcKcjdtjvgL0QGThy3RcecJQEDx3STrkkePL3dlyFCtVsmtQ0vjBBCxUgdySfxiobGGnpezZYi7q+Xz61GOZ9QqYmkcZOPzfNWeqtmzB7gqlH1gkFsK2yMAzKq2XCDFHvA7YAT3yMGiY06FcQ+2jyg7Bk2Q+AvjTG8hlPlmt6BZfW5cz1qx1apQn1qHXHrgfWcI52rApYQlNPOU1Uc8kZ8Ee6XUhhXBGY1rvZiKjKFG0PPuS8xo4/P7/u+gH5gItmEVDFL6giYPFsPpqAQkUN7hFoGiVZEjO4PwrLOmydsEcNOfACqrnUs08FQtvPg0sjHnxh6nh6FUQv93ukKl6+c9d+pCsN2xukrQ7Dog3nrjFZ6PrS5J0k9rDAOwTB55sfGXPZ2rATOK1WS4XcpsCtqwnYm4sGNc8ALMQkQ97zCnw8TcQwLvdUMlfbqQ5ykDQpQD68fITEDDHmBAeTCjpC713E6AhvOMwTJvjhd7hSkeOTRTmn9zXIVGNo1jSr8u0xO9uLGeWsV0+UlRLgp7/nsgfermjwNN8wj6MW3DHGS8UzzYfe9TGCeywqqIUTqgfXY48leGgB7twh4cl4jcOQniLATTvigIAQIvq/Uv8L45BGnkpKTdQ5F73gehXdVA",
16551665
type: 1,
@@ -1671,17 +1681,74 @@ describe(OlmMachine.name, () => {
16711681
undefined,
16721682
);
16731683

1674-
const receivedToDevices = JSON.parse(received);
1675-
expect(receivedToDevices).toBeInstanceOf(Array);
1676-
const receivedToDeviceArray: Array<any> = receivedToDevices;
1677-
expect(receivedToDeviceArray.length).toBe(1);
1678-
const toDeviceEvent = receivedToDeviceArray[0];
1684+
expect(received.length).toBe(1);
1685+
const processed = received[0];
1686+
expect(processed.type).toEqual(ProcessedToDeviceEventType.UnableToDecrypt);
1687+
1688+
let toDeviceEvent = JSON.parse(processed.wireEvent);
16791689

16801690
expect(toDeviceEvent.sender).toEqual("@bob:example.org");
16811691
expect(toDeviceEvent.type).toEqual("m.room.encrypted");
16821692
expect(toDeviceEvent.content.ciphertext).toBeDefined();
16831693
});
16841694

1695+
test("Should return invalid event properly", async () => {
1696+
const m = await machine();
1697+
1698+
let eventWithNoType = {
1699+
sender: "@alice:example.com",
1700+
content: {
1701+
algorithm: "m.megolm.v1.aes-sha2",
1702+
code: "m.unverified",
1703+
reason: "Device not verified",
1704+
room_id: "!Cuyf34gef24t:localhost",
1705+
sender_key: "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU",
1706+
session_id: "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ",
1707+
},
1708+
};
1709+
1710+
const eventWithMalformedCurveKey = {
1711+
content: {
1712+
"algorithm": "m.olm.v1.curve25519-aes-sha2",
1713+
"ciphertext": {
1714+
INVALID_CURVE: {
1715+
// this payload is just captured from a sync of some other element web with other users
1716+
body: "Awogjvpx458CGhuo77HX/",
1717+
type: 1,
1718+
},
1719+
},
1720+
"org.matrix.msgid": "93ee0170aa7740d0ac9ee137e820302d",
1721+
"sender_key": "WJ6Ce7U67a6jqkHYHd8o0+5H4bqdi9hInZdk0+swuXs",
1722+
},
1723+
type: "m.room.encrypted",
1724+
sender: "@bob:example.org",
1725+
};
1726+
1727+
let toDeviceEvents = [eventWithNoType, eventWithMalformedCurveKey];
1728+
1729+
const received = await m.receiveSyncChanges(
1730+
JSON.stringify(toDeviceEvents),
1731+
new DeviceLists(),
1732+
new Map<string, number>(),
1733+
undefined,
1734+
);
1735+
1736+
expect(received.length).toBe(2);
1737+
const processed0 = received[0];
1738+
expect(processed0.type).toEqual(ProcessedToDeviceEventType.Invalid);
1739+
const processed1 = received[1];
1740+
expect(processed1.type).toEqual(ProcessedToDeviceEventType.Invalid);
1741+
1742+
let toDeviceEvent0 = JSON.parse(processed0.wireEvent);
1743+
expect(toDeviceEvent0.sender).toEqual("@alice:example.com");
1744+
expect(toDeviceEvent0.content).toBeDefined();
1745+
expect(toDeviceEvent0.type).toBeUndefined();
1746+
1747+
let toDeviceEvent1 = JSON.parse(processed1.wireEvent);
1748+
expect(toDeviceEvent1.sender).toEqual("@bob:example.org");
1749+
expect(toDeviceEvent1.type).toEqual("m.room.encrypted");
1750+
});
1751+
16851752
test("Should return the clear text version of decrypted events", async () => {
16861753
const aliceUserId = new UserId("@alice:example.org");
16871754
const aliceDeviceId = new DeviceId("ALICE_DEV");
@@ -1776,12 +1843,11 @@ describe(OlmMachine.name, () => {
17761843
undefined,
17771844
);
17781845

1779-
const receivedToDevices = JSON.parse(received);
1780-
expect(receivedToDevices).toBeInstanceOf(Array);
1781-
const receivedToDeviceArray: Array<any> = receivedToDevices;
1782-
expect(receivedToDeviceArray.length).toBe(1);
1783-
const toDeviceEvent = receivedToDeviceArray[0];
1846+
expect(received.length).toBe(1);
1847+
const processed = received[0];
1848+
expect(processed.type).toEqual(ProcessedToDeviceEventType.Decrypted);
17841849

1850+
let toDeviceEvent = JSON.parse(processed.wireEvent);
17851851
expect(toDeviceEvent.sender).toEqual("@alice:example.org");
17861852
expect(toDeviceEvent.type).toEqual("custom.type");
17871853
expect(toDeviceEvent.content.foo).toEqual("bar");

0 commit comments

Comments
 (0)