Skip to content

Commit ff32840

Browse files
authored
refactor(crypto): Move session_id from EncryptionInfo to AlgorithmInfo as it is megolm specific
This patch moves the `session_id` field from EncryptionInfo to AlgorithmInfo::MegolmV1AesSha2 as it is specific to Megolm. We provide transparent migration of the serialized data from one format to the other. In the future we plan to reuse `EncryptionInfo` for to_device decryption (using olm not megolm). So megolm session_id should move to algorithm specific data.
1 parent b4afb91 commit ff32840

File tree

11 files changed

+135
-45
lines changed

11 files changed

+135
-45
lines changed

bindings/matrix-sdk-crypto-ffi/src/machine.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -917,21 +917,21 @@ impl OlmMachine {
917917
let event_json: Event<'_> = serde_json::from_str(decrypted.event.json().get())?;
918918

919919
Ok(match &encryption_info.algorithm_info {
920-
AlgorithmInfo::MegolmV1AesSha2 { curve25519_key, sender_claimed_keys } => {
921-
DecryptedEvent {
922-
clear_event: serde_json::to_string(&event_json)?,
923-
sender_curve25519_key: curve25519_key.to_owned(),
924-
claimed_ed25519_key: sender_claimed_keys
925-
.get(&DeviceKeyAlgorithm::Ed25519)
926-
.cloned(),
927-
forwarding_curve25519_chain: vec![],
928-
shield_state: if strict_shields {
929-
encryption_info.verification_state.to_shield_state_strict().into()
930-
} else {
931-
encryption_info.verification_state.to_shield_state_lax().into()
932-
},
933-
}
934-
}
920+
AlgorithmInfo::MegolmV1AesSha2 {
921+
curve25519_key,
922+
sender_claimed_keys,
923+
session_id: _,
924+
} => DecryptedEvent {
925+
clear_event: serde_json::to_string(&event_json)?,
926+
sender_curve25519_key: curve25519_key.to_owned(),
927+
claimed_ed25519_key: sender_claimed_keys.get(&DeviceKeyAlgorithm::Ed25519).cloned(),
928+
forwarding_curve25519_chain: vec![],
929+
shield_state: if strict_shields {
930+
encryption_info.verification_state.to_shield_state_strict().into()
931+
} else {
932+
encryption_info.verification_state.to_shield_state_lax().into()
933+
},
934+
},
935935
})
936936
}
937937

crates/matrix-sdk-base/src/event_cache/store/integration_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ pub fn make_test_event_with_event_id(
6262
algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
6363
curve25519_key: "1337".to_owned(),
6464
sender_claimed_keys: Default::default(),
65+
session_id: Some("mysessionid9".to_owned()),
6566
},
6667
verification_state: VerificationState::Verified,
67-
session_id: Some("mysessionid9".to_owned()),
6868
};
6969

7070
let mut builder = EventFactory::new().text_msg(content).room(room_id).sender(*ALICE);

crates/matrix-sdk-common/src/deserialized_responses.rs

Lines changed: 89 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -281,11 +281,16 @@ pub enum AlgorithmInfo {
281281
/// decrypt this session. This map will usually contain a single ed25519
282282
/// key.
283283
sender_claimed_keys: BTreeMap<DeviceKeyAlgorithm, String>,
284+
285+
/// The Megolm session ID that was used to encrypt this event, or None
286+
/// if this info was stored before we collected this data.
287+
#[serde(default, skip_serializing_if = "Option::is_none")]
288+
session_id: Option<String>,
284289
},
285290
}
286291

287292
/// Struct containing information on how an event was decrypted.
288-
#[derive(Clone, Debug, Deserialize, Serialize)]
293+
#[derive(Clone, Debug, Serialize)]
289294
pub struct EncryptionInfo {
290295
/// The user ID of the event sender, note this is untrusted data unless the
291296
/// `verification_state` is `Verified` as well.
@@ -302,9 +307,54 @@ pub struct EncryptionInfo {
302307
/// Callers that persist this should mark the state as dirty when a device
303308
/// change is received down the sync.
304309
pub verification_state: VerificationState,
305-
/// The Megolm session ID that was used to encrypt this event, or None if
306-
/// this info was stored before we collected this data.
307-
pub session_id: Option<String>,
310+
}
311+
312+
impl EncryptionInfo {
313+
/// Helper to get the megolm session id used to encrypt.
314+
pub fn session_id(&self) -> Option<&str> {
315+
let AlgorithmInfo::MegolmV1AesSha2 { session_id, .. } = &self.algorithm_info;
316+
session_id.as_deref()
317+
}
318+
}
319+
320+
impl<'de> Deserialize<'de> for EncryptionInfo {
321+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
322+
where
323+
D: serde::Deserializer<'de>,
324+
{
325+
// Backwards compatibility: Capture session_id at root if exists. In legacy
326+
// EncryptionInfo the session_id was not in AlgorithmInfo
327+
#[derive(Deserialize)]
328+
struct Helper {
329+
pub sender: OwnedUserId,
330+
pub sender_device: Option<OwnedDeviceId>,
331+
pub algorithm_info: AlgorithmInfo,
332+
pub verification_state: VerificationState,
333+
#[serde(rename = "session_id")]
334+
pub old_session_id: Option<String>,
335+
}
336+
337+
let Helper {
338+
sender,
339+
sender_device,
340+
algorithm_info:
341+
AlgorithmInfo::MegolmV1AesSha2 { curve25519_key, sender_claimed_keys, session_id },
342+
verification_state,
343+
old_session_id,
344+
} = Helper::deserialize(deserializer)?;
345+
346+
Ok(EncryptionInfo {
347+
sender,
348+
sender_device,
349+
algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
350+
// Migration, merge the old_session_id in algorithm_info
351+
session_id: session_id.or(old_session_id),
352+
curve25519_key,
353+
sender_claimed_keys,
354+
},
355+
verification_state,
356+
})
357+
}
308358
}
309359

310360
/// Represents a matrix room event that has been returned from `/sync`,
@@ -549,12 +599,11 @@ impl TimelineEventKind {
549599
pub fn session_id(&self) -> Option<&str> {
550600
match self {
551601
TimelineEventKind::Decrypted(decrypted_room_event) => {
552-
decrypted_room_event.encryption_info.session_id.as_ref()
602+
decrypted_room_event.encryption_info.session_id()
553603
}
554-
TimelineEventKind::UnableToDecrypt { utd_info, .. } => utd_info.session_id.as_ref(),
604+
TimelineEventKind::UnableToDecrypt { utd_info, .. } => utd_info.session_id.as_deref(),
555605
TimelineEventKind::PlainText { .. } => None,
556606
}
557-
.map(String::as_str)
558607
}
559608
}
560609

@@ -1056,9 +1105,9 @@ mod tests {
10561105
algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
10571106
curve25519_key: "xxx".to_owned(),
10581107
sender_claimed_keys: Default::default(),
1108+
session_id: Some("xyz".to_owned()),
10591109
},
10601110
verification_state: VerificationState::Verified,
1061-
session_id: Some("xyz".to_owned()),
10621111
},
10631112
unsigned_encryption_info: Some(BTreeMap::from([(
10641113
UnsignedEventLocation::RelationsReplace,
@@ -1093,11 +1142,11 @@ mod tests {
10931142
"algorithm_info": {
10941143
"MegolmV1AesSha2": {
10951144
"curve25519_key": "xxx",
1096-
"sender_claimed_keys": {}
1145+
"sender_claimed_keys": {},
1146+
"session_id": "xyz",
10971147
}
10981148
},
10991149
"verification_state": "Verified",
1100-
"session_id": "xyz",
11011150
},
11021151
"unsigned_encryption_info": {
11031152
"RelationsReplace": {"UnableToDecrypt": {
@@ -1144,9 +1193,8 @@ mod tests {
11441193
assert_eq!(event.event_id(), Some(event_id!("$xxxxx:example.org").to_owned()));
11451194
assert_matches!(
11461195
event.encryption_info().unwrap().algorithm_info,
1147-
AlgorithmInfo::MegolmV1AesSha2 { .. }
1196+
AlgorithmInfo::MegolmV1AesSha2 { session_id: None, .. }
11481197
);
1149-
assert_eq!(event.encryption_info().unwrap().session_id, None);
11501198

11511199
// Test that the previous format, with an undecryptable unsigned event, can also
11521200
// be deserialized.
@@ -1366,13 +1414,40 @@ mod tests {
13661414
(DeviceKeyAlgorithm::Curve25519, "claimedclaimedcurve25519".to_owned()),
13671415
(DeviceKeyAlgorithm::Ed25519, "claimedclaimeded25519".to_owned()),
13681416
]),
1417+
session_id: None,
13691418
};
13701419

13711420
with_settings!({ prepend_module_to_snapshot => false }, {
13721421
assert_json_snapshot!(info)
13731422
});
13741423
}
13751424

1425+
#[test]
1426+
fn test_encryption_info_migration() {
1427+
// In the old format the session_id was in the EncryptionInfo, now
1428+
// it is moved to the `algorithm_info` struct.
1429+
let old_format = json!({
1430+
"sender": "@alice:localhost",
1431+
"sender_device": "ABCDEFGH",
1432+
"algorithm_info": {
1433+
"MegolmV1AesSha2": {
1434+
"curve25519_key": "curvecurvecurve",
1435+
"sender_claimed_keys": {}
1436+
}
1437+
},
1438+
"verification_state": "Verified",
1439+
"session_id": "mysessionid76"
1440+
});
1441+
1442+
let deserialized = serde_json::from_value::<EncryptionInfo>(old_format).unwrap();
1443+
let expected_session_id = Some("mysessionid76".to_owned());
1444+
1445+
let AlgorithmInfo::MegolmV1AesSha2 { session_id, .. } = deserialized.algorithm_info.clone();
1446+
assert_eq!(session_id, expected_session_id);
1447+
1448+
assert_json_snapshot!(deserialized);
1449+
}
1450+
13761451
#[test]
13771452
fn snapshot_test_encryption_info() {
13781453
let info = EncryptionInfo {
@@ -1381,9 +1456,9 @@ mod tests {
13811456
algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
13821457
curve25519_key: "curvecurvecurve".into(),
13831458
sender_claimed_keys: Default::default(),
1459+
session_id: Some("mysessionid76".to_owned()),
13841460
},
13851461
verification_state: VerificationState::Verified,
1386-
session_id: Some("mysessionid76".to_owned()),
13871462
};
13881463

13891464
with_settings!({ sort_maps => true, prepend_module_to_snapshot => false }, {
@@ -1411,9 +1486,9 @@ mod tests {
14111486
"qzdW3F5IMPFl0HQgz5w/L5Oi/npKUFn8Um84acIHfPY".to_owned(),
14121487
),
14131488
]),
1489+
session_id: Some("mysessionid112".to_owned()),
14141490
},
14151491
verification_state: VerificationState::Verified,
1416-
session_id: Some("mysessionid112".to_owned()),
14171492
},
14181493
unsigned_encryption_info: Some(BTreeMap::from([(
14191494
UnsignedEventLocation::RelationsThreadLatestEvent,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
source: crates/matrix-sdk-common/src/deserialized_responses.rs
3+
expression: deserialized
4+
---
5+
{
6+
"sender": "@alice:localhost",
7+
"sender_device": "ABCDEFGH",
8+
"algorithm_info": {
9+
"MegolmV1AesSha2": {
10+
"curve25519_key": "curvecurvecurve",
11+
"sender_claimed_keys": {},
12+
"session_id": "mysessionid76"
13+
}
14+
},
15+
"verification_state": "Verified"
16+
}
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---
22
source: crates/matrix-sdk-common/src/deserialized_responses.rs
3-
assertion_line: 1360
43
expression: info
54
---
65
{
@@ -9,9 +8,9 @@ expression: info
98
"algorithm_info": {
109
"MegolmV1AesSha2": {
1110
"curve25519_key": "curvecurvecurve",
12-
"sender_claimed_keys": {}
11+
"sender_claimed_keys": {},
12+
"session_id": "mysessionid76"
1313
}
1414
},
15-
"verification_state": "Verified",
16-
"session_id": "mysessionid76"
15+
"verification_state": "Verified"
1716
}

crates/matrix-sdk-common/src/snapshots/snapshot_test_sync_timeline_event.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ expression: "serde_json::to_value(&room_event).unwrap()"
1212
"sender_claimed_keys": {
1313
"curve25519": "qzdW3F5IMPFl0HQgz5w/L5Oi/npKUFn8Um84acIHfPY",
1414
"ed25519": "I3YsPwqMZQXHkSQbjFNEs7b529uac2xBpI83eN3LUXo"
15-
}
15+
},
16+
"session_id": "mysessionid112"
1617
}
1718
},
1819
"sender": "@sender:example.com",
1920
"sender_device": "ABCDEFGHIJ",
20-
"session_id": "mysessionid112",
2121
"verification_state": "Verified"
2222
},
2323
"event": {

crates/matrix-sdk-crypto/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ All notable changes to this project will be documented in this file.
88

99
### Features
1010

11+
- [**breaking**] Move `session_id` from `EncryptionInfo` to `AlgorithmInfo` as it is megolm specific.
12+
Use `EncryptionInfo::session_id()` helper for quick access.
13+
1114
- Send stable identifier `sender_device_keys` for MSC4147 (Including device
1215
keys with Olm-encrypted events).
1316
([#4964](https://github.com/matrix-org/matrix-rust-sdk/pull/4964))

crates/matrix-sdk-crypto/src/machine/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1720,9 +1720,9 @@ impl OlmMachine {
17201720
.iter()
17211721
.map(|(k, v)| (k.to_owned(), v.to_base64()))
17221722
.collect(),
1723+
session_id: Some(session.session_id().to_owned()),
17231724
},
17241725
verification_state,
1725-
session_id: Some(session.session_id().to_owned()),
17261726
})
17271727
}
17281728

crates/matrix-sdk-ui/src/timeline/controller/decryption_retry_task.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,7 @@ fn compute_event_indices_to_retry_decryption(
174174
} else {
175175
// Non-UTDs only have a session ID if they are remote and have it in the
176176
// EncryptionInfo
177-
event
178-
.as_remote()
179-
.and_then(|remote| remote.encryption_info.as_ref()?.session_id.as_ref())
180-
.map(String::as_str)
177+
event.as_remote().and_then(|remote| remote.encryption_info.as_ref()?.session_id())
181178
};
182179

183180
if let Some(session_id) = session_id {
@@ -232,7 +229,7 @@ async fn make_replacement_for<P: RoomDataProvider>(
232229
let item = item?;
233230
let event = item.as_event()?;
234231
let remote = event.as_remote()?;
235-
let session_id = remote.encryption_info.as_ref()?.session_id.as_deref()?;
232+
let session_id = remote.encryption_info.as_ref()?.session_id()?;
236233

237234
let new_encryption_info =
238235
room_data_provider.get_encryption_info(session_id, &event.sender).await;
@@ -515,9 +512,9 @@ mod tests {
515512
algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
516513
curve25519_key: "".to_owned(),
517514
sender_claimed_keys: BTreeMap::new(),
515+
session_id: Some(session_id.to_owned()),
518516
},
519517
verification_state: VerificationState::Verified,
520-
session_id: Some(session_id.to_owned()),
521518
}),
522519
original_json: None,
523520
latest_edit_json: None,

crates/matrix-sdk-ui/src/timeline/tests/edit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@ async fn test_edit_updates_encryption_info() {
173173
algorithm_info: AlgorithmInfo::MegolmV1AesSha2 {
174174
curve25519_key: "123".to_owned(),
175175
sender_claimed_keys: BTreeMap::new(),
176+
session_id: Some("mysessionid6333".to_owned()),
176177
},
177178
verification_state: VerificationState::Verified,
178-
session_id: Some("mysessionid6333".to_owned()),
179179
};
180180

181181
let original_event: TimelineEvent = DecryptedRoomEvent {

0 commit comments

Comments
 (0)