From 5c93372e8aff9f716b91bb98635b32b9df586923 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 25 Jun 2024 11:17:54 +0200 Subject: [PATCH] refactor(sdk-crypto) - RoomKey Sharing | More test --- .../group_sessions/share_strategy.rs | 280 +++++++++++ .../src/test_json/keys_query_sets.rs | 459 ++++++++++++++++++ testing/matrix-sdk-test/src/test_json/mod.rs | 1 + 3 files changed, 740 insertions(+) create mode 100644 testing/matrix-sdk-test/src/test_json/keys_query_sets.rs diff --git a/crates/matrix-sdk-crypto/src/session_manager/group_sessions/share_strategy.rs b/crates/matrix-sdk-crypto/src/session_manager/group_sessions/share_strategy.rs index 25f4ceeb610..5e2e295d255 100644 --- a/crates/matrix-sdk-crypto/src/session_manager/group_sessions/share_strategy.rs +++ b/crates/matrix-sdk-crypto/src/session_manager/group_sessions/share_strategy.rs @@ -224,3 +224,283 @@ fn split_recipients_withhelds_for_user( RecipientDevices { allowed_devices: recipients, denied_devices_with_code: withheld_recipients } } + +#[cfg(test)] +mod tests { + + use std::sync::Arc; + + use matrix_sdk_test::{async_test, test_json::keys_query_sets::KeyDistributionTestData}; + use ruma::{events::room::history_visibility::HistoryVisibility, room_id, TransactionId}; + + use crate::{ + olm::OutboundGroupSession, + session_manager::{ + group_sessions::share_strategy::collect_session_recipients, CollectStrategy, + }, + types::events::room_key_withheld::WithheldCode, + CrossSigningKeyExport, EncryptionSettings, OlmMachine, + }; + + async fn set_up_test_machine() -> OlmMachine { + let machine = OlmMachine::new( + KeyDistributionTestData::me_id(), + KeyDistributionTestData::me_device_id(), + ) + .await; + + let keys_query = KeyDistributionTestData::me_keys_query_response(); + let txn_id = TransactionId::new(); + machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap(); + + machine + .import_cross_signing_keys(CrossSigningKeyExport { + master_key: KeyDistributionTestData::MASTER_KEY_PRIVATE_EXPORT.to_owned().into(), + self_signing_key: KeyDistributionTestData::SELF_SIGNING_KEY_PRIVATE_EXPORT + .to_owned() + .into(), + user_signing_key: KeyDistributionTestData::USER_SIGNING_KEY_PRIVATE_EXPORT + .to_owned() + .into(), + }) + .await + .unwrap(); + + let keys_query = KeyDistributionTestData::dan_keys_query_response(); + let txn_id = TransactionId::new(); + machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap(); + + let txn_id_dave = TransactionId::new(); + let keys_query_dave = KeyDistributionTestData::dave_keys_query_response(); + machine.mark_request_as_sent(&txn_id_dave, &keys_query_dave).await.unwrap(); + + let txn_id_good = TransactionId::new(); + let keys_query_good = KeyDistributionTestData::good_keys_query_response(); + machine.mark_request_as_sent(&txn_id_good, &keys_query_good).await.unwrap(); + + machine + } + + #[async_test] + async fn test_share_with_per_device_strategy_to_all() { + let machine = set_up_test_machine().await; + + let legacy_strategy = CollectStrategy::new_device_based(false); + + let encryption_settings = + EncryptionSettings { sharing_strategy: legacy_strategy.clone(), ..Default::default() }; + + let fake_room_id = room_id!("!roomid:localhost"); + + let id_keys = machine.identity_keys(); + let group_session = OutboundGroupSession::new( + machine.device_id().into(), + Arc::new(id_keys), + fake_room_id, + encryption_settings.clone(), + ) + .unwrap(); + + let share_result = collect_session_recipients( + machine.store(), + vec![ + KeyDistributionTestData::dan_id(), + KeyDistributionTestData::dave_id(), + KeyDistributionTestData::good_id(), + ] + .into_iter(), + &encryption_settings, + &group_session, + ) + .await + .unwrap(); + + assert!(!share_result.should_rotate); + + let dan_devices_shared = + share_result.devices.get(KeyDistributionTestData::dan_id()).unwrap(); + let dave_devices_shared = + share_result.devices.get(KeyDistributionTestData::dave_id()).unwrap(); + let good_devices_shared = + share_result.devices.get(KeyDistributionTestData::good_id()).unwrap(); + + // With this strategy the room key would be distributed to all devices + assert_eq!(dan_devices_shared.len(), 2); + assert_eq!(dave_devices_shared.len(), 1); + assert_eq!(good_devices_shared.len(), 2); + } + + #[async_test] + async fn test_share_with_per_device_strategy_only_trusted() { + let machine = set_up_test_machine().await; + + let fake_room_id = room_id!("!roomid:localhost"); + + let legacy_strategy = CollectStrategy::new_device_based(true); + + let encryption_settings = + EncryptionSettings { sharing_strategy: legacy_strategy.clone(), ..Default::default() }; + + let id_keys = machine.identity_keys(); + let group_session = OutboundGroupSession::new( + machine.device_id().into(), + Arc::new(id_keys), + fake_room_id, + encryption_settings.clone(), + ) + .unwrap(); + + let share_result = collect_session_recipients( + machine.store(), + vec![ + KeyDistributionTestData::dan_id(), + KeyDistributionTestData::dave_id(), + KeyDistributionTestData::good_id(), + ] + .into_iter(), + &encryption_settings, + &group_session, + ) + .await + .unwrap(); + + assert!(!share_result.should_rotate); + + let dave_devices_shared = share_result.devices.get(KeyDistributionTestData::dave_id()); + let good_devices_shared = share_result.devices.get(KeyDistributionTestData::good_id()); + // dave and good wouldn't receive any key + assert!(dave_devices_shared.unwrap().is_empty()); + assert!(good_devices_shared.unwrap().is_empty()); + + // dan is verified by me and has one of his devices self signed, so should get + // the key + let dan_devices_shared = + share_result.devices.get(KeyDistributionTestData::dan_id()).unwrap(); + + assert_eq!(dan_devices_shared.len(), 1); + let dan_device_that_will_get_the_key = &dan_devices_shared[0]; + assert_eq!( + dan_device_that_will_get_the_key.device_id().as_str(), + KeyDistributionTestData::dan_signed_device_id() + ); + + // Check withhelds for others + let (_, code) = share_result + .withheld_devices + .iter() + .find(|(d, _)| d.device_id() == KeyDistributionTestData::dan_unsigned_device_id()) + .expect("This dan's device should receive a withheld code"); + + assert_eq!(code.as_str(), WithheldCode::Unverified.as_str()); + + let (_, code) = share_result + .withheld_devices + .iter() + .find(|(d, _)| d.device_id() == KeyDistributionTestData::dave_device_id()) + .expect("This daves's device should receive a withheld code"); + + assert_eq!(code.as_str(), WithheldCode::Unverified.as_str()); + } + + #[async_test] + async fn test_should_rotate_based_on_visibility() { + let machine = set_up_test_machine().await; + + let fake_room_id = room_id!("!roomid:localhost"); + + let strategy = CollectStrategy::new_device_based(false); + + let encryption_settings = EncryptionSettings { + sharing_strategy: strategy.clone(), + history_visibility: HistoryVisibility::Invited, + ..Default::default() + }; + + let id_keys = machine.identity_keys(); + let group_session = OutboundGroupSession::new( + machine.device_id().into(), + Arc::new(id_keys), + fake_room_id, + encryption_settings.clone(), + ) + .unwrap(); + + let _ = collect_session_recipients( + machine.store(), + vec![KeyDistributionTestData::dan_id()].into_iter(), + &encryption_settings, + &group_session, + ) + .await + .unwrap(); + + // Try to share again with updated history visibility + let encryption_settings = EncryptionSettings { + sharing_strategy: strategy.clone(), + history_visibility: HistoryVisibility::Shared, + ..Default::default() + }; + + let share_result = collect_session_recipients( + machine.store(), + vec![KeyDistributionTestData::dan_id()].into_iter(), + &encryption_settings, + &group_session, + ) + .await + .unwrap(); + + assert!(share_result.should_rotate); + } + + /// Test that the session is rotated when a device is removed from the + /// recipients. In that case we simulate that dan has logged out one of + /// his devices. + #[async_test] + async fn test_should_rotate_based_on_device_excluded() { + let machine = set_up_test_machine().await; + + let fake_room_id = room_id!("!roomid:localhost"); + + let strategy = CollectStrategy::new_device_based(false); + + let encryption_settings = + EncryptionSettings { sharing_strategy: strategy.clone(), ..Default::default() }; + + let requests = machine + .share_room_key( + fake_room_id, + vec![KeyDistributionTestData::dan_id()].into_iter(), + encryption_settings.clone(), + ) + .await + .unwrap(); + + for r in requests { + machine + .inner + .group_session_manager + .mark_request_as_sent(r.as_ref().txn_id.as_ref()) + .await + .unwrap(); + } + // Try to share again after dan has removed one of his devices + let keys_query = KeyDistributionTestData::dan_keys_query_response_device_loggedout(); + let txn_id = TransactionId::new(); + machine.mark_request_as_sent(&txn_id, &keys_query).await.unwrap(); + + let group_session = + machine.store().get_outbound_group_session(fake_room_id).await.unwrap().unwrap(); + // share again + let share_result = collect_session_recipients( + machine.store(), + vec![KeyDistributionTestData::dan_id()].into_iter(), + &encryption_settings, + &group_session, + ) + .await + .unwrap(); + + assert!(share_result.should_rotate); + } +} diff --git a/testing/matrix-sdk-test/src/test_json/keys_query_sets.rs b/testing/matrix-sdk-test/src/test_json/keys_query_sets.rs new file mode 100644 index 00000000000..c4e06e190fc --- /dev/null +++ b/testing/matrix-sdk-test/src/test_json/keys_query_sets.rs @@ -0,0 +1,459 @@ +use ruma::{ + api::{client::keys::get_keys::v3::Response as KeyQueryResponse, IncomingResponse}, + device_id, user_id, DeviceId, UserId, +}; +use serde_json::json; + +use crate::response_from_file; + +/// This set of keys/query response was generated using a local synapse. +/// Each users was created, device added according to needs and the payload +/// of the keys query have been copy/pasted here. +/// +/// The current user is `@me:localhost`, the private part of the +/// cross-signing keys have been exported using the console with the +/// following snippet: `await mxMatrixClientPeg.get().getCrypto(). +/// olmMachine.exportCrossSigningKeys()`. +/// +/// They are imported in the test here in order to verify user signatures. +/// +/// * `@me:localhost` is the current user mxId. +/// +/// * `@dan:localhost` is a user with cross-signing enabled, with 2 devices. One +/// device (`JHPUERYQUW`) is self signed by @dan, but not the other one +/// (`FRGNMZVOKA`). `@me` has verified `@dan`, can be seen because `@dan` +/// master key has a signature by `@me` ssk +/// +/// * `@dave` is a user that has not enabled cross-signing. And has one device +/// (`HVCXJTHMBM`). +/// +/// +/// * `@good` is a user with cross-signing enabled, with 2 devices. The 2 +/// devices are properly signed by `@good` (i.e were self-verified by @good) +pub struct KeyDistributionTestData {} + +#[allow(dead_code)] +impl KeyDistributionTestData { + pub const MASTER_KEY_PRIVATE_EXPORT: &'static str = + "9kquJqAtEUoTXljh5W2QSsCm4FH9WvWzIkDkIMUsM2k"; + pub const SELF_SIGNING_KEY_PRIVATE_EXPORT: &'static str = + "QifnGfudByh/GpBgJYEMzq7/DGbp6fZjp58faQj3n1M"; + pub const USER_SIGNING_KEY_PRIVATE_EXPORT: &'static str = + "zQSosK46giUFs2ACsaf32bA7drcIXbmViyEt+TLfloI"; + + /// Current user keys query response containing the cross-signing keys + pub fn me_keys_query_response() -> KeyQueryResponse { + let data = json!({ + "master_keys": { + "@me:localhost": { + "keys": { + "ed25519:KOS8zz9SJnMOxpfPOx9LO2+abuEcnZP/lxDo5RsXao4": "KOS8zz9SJnMOxpfPOx9LO2+abuEcnZP/lxDo5RsXao4" + }, + "signatures": { + "@me:localhost": { + "ed25519:KOS8zz9SJnMOxpfPOx9LO2+abuEcnZP/lxDo5RsXao4": "5G9+Ns28rzNd+2DvP73Y0orr8sxduRQcrJj0YB7ZygH7oeXshvGLeQn6mcNs7q7ZrMR5bYlXxopufKSWWoKpCg", + "ed25519:YVKUSVBKWX": "ih1Kmj4dTB1AjjkwrLA2qIL3e/oPUFisP5Ic8kGp29wrpoHokasKKnkRl1zS7zq6iBcOL6aOZLPPX/ZHYCX5BQ" + } + }, + "usage": [ + "master" + ], + "user_id": "@me:localhost" + } + }, + "self_signing_keys": { + "@me:localhost": { + "keys": { + "ed25519:9gXJQzvqZ+KQunfBTd0g9AkrulwEeFfspyWTSQFqqrw": "9gXJQzvqZ+KQunfBTd0g9AkrulwEeFfspyWTSQFqqrw" + }, + "signatures": { + "@me:localhost": { + "ed25519:KOS8zz9SJnMOxpfPOx9LO2+abuEcnZP/lxDo5RsXao4": "amiKDLpWIwUQPzq+eov6KJsoskkWA1YzrGNb7HF3OcGV0nm4t7df0tUdZB/OpREtT5D78BKtzOPUipde2DxUAw" + } + }, + "usage": [ + "self_signing" + ], + "user_id": "@me:localhost" + } + }, + "user_signing_keys": { + "@me:localhost": { + "keys": { + "ed25519:mvzOc2EuHoVfZTk1hX3y0hyjUs4MrfPv2V/PUFzMQJY": "mvzOc2EuHoVfZTk1hX3y0hyjUs4MrfPv2V/PUFzMQJY" + }, + "signatures": { + "@me:localhost": { + "ed25519:KOS8zz9SJnMOxpfPOx9LO2+abuEcnZP/lxDo5RsXao4": "Cv56vTHAzRkvdcELleOlhECZQP0pXcikCdEZrnXbkjXQ/k0ZvVOJ1beG/SiH8xc6zh1bCIMYv96C9p8o+7VZCQ" + } + }, + "usage": [ + "user_signing" + ], + "user_id": "@me:localhost" + } + } + }); + + let data = response_from_file(&data); + + KeyQueryResponse::try_from_http_response(data) + .expect("Can't parse the `/keys/upload` response") + } + + /// Dan has cross-signing setup, one device is cross signed `JHPUERYQUW`, + /// but not the other one `FRGNMZVOKA`. + /// `@dan` identity is signed by `@me` identity (alice trust dan) + pub fn dan_keys_query_response() -> KeyQueryResponse { + let data: serde_json::Value = json!({ + "device_keys": { + "@dan:localhost": { + "JHPUERYQUW": { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": "JHPUERYQUW", + "keys": { + "curve25519:JHPUERYQUW": "PBo2nKbink/HxgzMrBftGPogsD0d47LlIMsViTpCRn4", + "ed25519:JHPUERYQUW": "jZ5Ca/J5RXn3qnNWIHFz9EQBZ4637QI/9ExSiEcGC7I" + }, + "signatures": { + "@dan:localhost": { + "ed25519:JHPUERYQUW": "PaVfCE9QODgluq0gYMpjCarfDbraRXU71uRcUN5MoqtiJYlB0bjzY6bD5/qxugrsgcx4DZOgCLgiyoEZ/vW4DQ", + "ed25519:aX+O6rO/RxzkygPd7XXilKM07aSFK4gSPK1Zxenr6ak": "2sZcF5aSyEuryTfWgsw3rNDevnZisH2Df6fCO5pmGwweiaD+n6+pyrzB75mvA1sOwzm9jfTsjv/2+Uj1CNOTBA" + } + }, + "user_id": "@dan:localhost", + }, + "FRGNMZVOKA": { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": "FRGNMZVOKA", + "keys": { + "curve25519:FRGNMZVOKA": "Hc/BC/xyQIEnScyZkEk+ilDMfOARxHMFoEcggPqqRw4", + "ed25519:FRGNMZVOKA": "jVroR0JoRemjF0vJslY3HirJgwfX5gm5DCM64hZgkI0" + }, + "signatures": { + "@dan:localhost": { + "ed25519:FRGNMZVOKA": "+row23EcWR2D8EKgwzZmy3dWz/l5DHvEHR6jHKnBohphEIsBl0o3Cp9rIztFpStFGRPSAa3xEqfMVW2dIaKkCg" + } + }, + "user_id": "@dan:localhost", + }, + } + }, + "failures": {}, + "master_keys": { + "@dan:localhost": { + "keys": { + "ed25519:Nj4qZEmWplA8tofkjcR+YOvRCYMRLDKY71BT9GFO32k": "Nj4qZEmWplA8tofkjcR+YOvRCYMRLDKY71BT9GFO32k" + }, + "signatures": { + "@dan:localhost": { + "ed25519:Nj4qZEmWplA8tofkjcR+YOvRCYMRLDKY71BT9GFO32k": "DI/zpWA/wG1tdK9aLof1TGBHtihtQZQ+7e62QRSBbo+RAHlQ+akGcaVskLbtLdEKbcJEt61F+Auol+XVGlCEBA", + "ed25519:SNEBMNPLHN": "5Y8byBteGZo1SvPf8QM88pvThJu+2mJ4020YsTLPhCQ4DfdalHWTPOvE7gw09cCONhX/cKY7YHMyH8R26Yd9DA" + }, + "@me:localhost": { + "ed25519:mvzOc2EuHoVfZTk1hX3y0hyjUs4MrfPv2V/PUFzMQJY": "vg2MLJx36Usti4NfsbOfk0ipW7koOoTlBibZkQNrPTMX88V+geTgDjvIMEU/OAyEsgsDHjg3C+2t/yUUDE7hBA" + } + }, + "usage": [ + "master" + ], + "user_id": "@dan:localhost" + } + }, + "self_signing_keys": { + "@dan:localhost": { + "keys": { + "ed25519:aX+O6rO/RxzkygPd7XXilKM07aSFK4gSPK1Zxenr6ak": "aX+O6rO/RxzkygPd7XXilKM07aSFK4gSPK1Zxenr6ak" + }, + "signatures": { + "@dan:localhost": { + "ed25519:Nj4qZEmWplA8tofkjcR+YOvRCYMRLDKY71BT9GFO32k": "vxUCzOO4EGwLp+tzfoFbPOVicynvmWgxVx/bv/3fG/Xfl7piJVmeHP+1qDstOewiREuO4W+ti/tYkOXd7GgoAw" + } + }, + "usage": [ + "self_signing" + ], + "user_id": "@dan:localhost" + } + }, + "user_signing_keys": { + "@dan:localhost": { + "keys": { + "ed25519:N4y+jN6GctRXyNDa1CFRdjofTTxHkNK9t430jE9DxrU": "N4y+jN6GctRXyNDa1CFRdjofTTxHkNK9t430jE9DxrU" + }, + "signatures": { + "@dan:localhost": { + "ed25519:Nj4qZEmWplA8tofkjcR+YOvRCYMRLDKY71BT9GFO32k": "gbcD579EGVDRePnKV9j6YNwGhssgFeJWhF1NRJhFNAcpbGL8911cW54jyiFKFCev89QemfqyFFljldFLfyN9DA" + } + }, + "usage": [ + "user_signing" + ], + "user_id": "@dan:localhost" + } + } + }); + + let data = response_from_file(&data); + + KeyQueryResponse::try_from_http_response(data) + .expect("Can't parse the `/keys/upload` response") + } + + /// Same as `dan_keys_query_response` but `FRGNMZVOKA` was removed. + pub fn dan_keys_query_response_device_loggedout() -> KeyQueryResponse { + let data = json!({ + "device_keys": { + "@dan:localhost": { + "JHPUERYQUW": { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": "JHPUERYQUW", + "keys": { + "curve25519:JHPUERYQUW": "PBo2nKbink/HxgzMrBftGPogsD0d47LlIMsViTpCRn4", + "ed25519:JHPUERYQUW": "jZ5Ca/J5RXn3qnNWIHFz9EQBZ4637QI/9ExSiEcGC7I" + }, + "signatures": { + "@dan:localhost": { + "ed25519:JHPUERYQUW": "PaVfCE9QODgluq0gYMpjCarfDbraRXU71uRcUN5MoqtiJYlB0bjzY6bD5/qxugrsgcx4DZOgCLgiyoEZ/vW4DQ", + "ed25519:aX+O6rO/RxzkygPd7XXilKM07aSFK4gSPK1Zxenr6ak": "2sZcF5aSyEuryTfWgsw3rNDevnZisH2Df6fCO5pmGwweiaD+n6+pyrzB75mvA1sOwzm9jfTsjv/2+Uj1CNOTBA" + } + }, + "user_id": "@dan:localhost", + }, + } + }, + "failures": {}, + "master_keys": { + "@dan:localhost": { + "keys": { + "ed25519:Nj4qZEmWplA8tofkjcR+YOvRCYMRLDKY71BT9GFO32k": "Nj4qZEmWplA8tofkjcR+YOvRCYMRLDKY71BT9GFO32k" + }, + "signatures": { + "@dan:localhost": { + "ed25519:Nj4qZEmWplA8tofkjcR+YOvRCYMRLDKY71BT9GFO32k": "DI/zpWA/wG1tdK9aLof1TGBHtihtQZQ+7e62QRSBbo+RAHlQ+akGcaVskLbtLdEKbcJEt61F+Auol+XVGlCEBA", + "ed25519:SNEBMNPLHN": "5Y8byBteGZo1SvPf8QM88pvThJu+2mJ4020YsTLPhCQ4DfdalHWTPOvE7gw09cCONhX/cKY7YHMyH8R26Yd9DA" + }, + "@me:localhost": { + "ed25519:mvzOc2EuHoVfZTk1hX3y0hyjUs4MrfPv2V/PUFzMQJY": "vg2MLJx36Usti4NfsbOfk0ipW7koOoTlBibZkQNrPTMX88V+geTgDjvIMEU/OAyEsgsDHjg3C+2t/yUUDE7hBA" + } + }, + "usage": [ + "master" + ], + "user_id": "@dan:localhost" + } + }, + "self_signing_keys": { + "@dan:localhost": { + "keys": { + "ed25519:aX+O6rO/RxzkygPd7XXilKM07aSFK4gSPK1Zxenr6ak": "aX+O6rO/RxzkygPd7XXilKM07aSFK4gSPK1Zxenr6ak" + }, + "signatures": { + "@dan:localhost": { + "ed25519:Nj4qZEmWplA8tofkjcR+YOvRCYMRLDKY71BT9GFO32k": "vxUCzOO4EGwLp+tzfoFbPOVicynvmWgxVx/bv/3fG/Xfl7piJVmeHP+1qDstOewiREuO4W+ti/tYkOXd7GgoAw" + } + }, + "usage": [ + "self_signing" + ], + "user_id": "@dan:localhost" + } + }, + "user_signing_keys": { + "@dan:localhost": { + "keys": { + "ed25519:N4y+jN6GctRXyNDa1CFRdjofTTxHkNK9t430jE9DxrU": "N4y+jN6GctRXyNDa1CFRdjofTTxHkNK9t430jE9DxrU" + }, + "signatures": { + "@dan:localhost": { + "ed25519:Nj4qZEmWplA8tofkjcR+YOvRCYMRLDKY71BT9GFO32k": "gbcD579EGVDRePnKV9j6YNwGhssgFeJWhF1NRJhFNAcpbGL8911cW54jyiFKFCev89QemfqyFFljldFLfyN9DA" + } + }, + "usage": [ + "user_signing" + ], + "user_id": "@dan:localhost" + } + } + }); + + let data = response_from_file(&data); + + KeyQueryResponse::try_from_http_response(data) + .expect("Can't parse the `/keys/upload` response") + } + + /// Dave is a user that has not enabled cross-signing + pub fn dave_keys_query_response() -> KeyQueryResponse { + let data = json!({ + "device_keys": { + "@dave:localhost": { + "HVCXJTHMBM": { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": "HVCXJTHMBM", + "keys": { + "curve25519:HVCXJTHMBM": "0GPOoQwhAGVu1lIvOZway3/XjdxVNHEi5z/4by8TzxU", + "ed25519:HVCXJTHMBM": "/4ZzD1Ou70/Ojj5aaPqBopCN8SzQpKM7itiWZ/07fXc" + }, + "signatures": { + "@dave:localhost": { + "ed25519:HVCXJTHMBM": "b1DV7xN2My2oXbZVVtTeJR9hzXIg1Cx4h+W51+tVq5GAoSYtrWR31PyKPROk28CvQ9Pu++/jdomaW7/oYPxoCg", + } + }, + "user_id": "@dave:localhost", + } + } + } + }); + + let data = response_from_file(&data); + + KeyQueryResponse::try_from_http_response(data) + .expect("Can't parse the `/keys/upload` response") + } + + /// Good is a user that has all his devices correctly cross-signed + pub fn good_keys_query_response() -> KeyQueryResponse { + let data = json!({ + "device_keys": { + "@good:localhost": { + "JAXGBVZYLA": { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": "JAXGBVZYLA", + "keys": { + "curve25519:JAXGBVZYLA": "a4vWxnHUKvELfB7WYLCW07vEbwybZReyKReWHxQhgW0", + "ed25519:JAXGBVZYLA": "m22nVxqJK72iph+FhOMqX/MDd7AoF9BJ033MlMLnDCg" + }, + "signatures": { + "@good:localhost": { + "ed25519:JAXGBVZYLA": "EXKQiXNKjWSE76WxF8TUvxjCyw/qsV27gcbsgpSN1zzHzGzVdY1Qr4EB8t/76SL5rZP/9hqcAvqPSJW/N7iKCg", + "ed25519:YwQVBWn2sA5lLqp/dQsNk7fiYOuQuQhujefOPjejc+U": "sXJUXKE7hqXnsNbqlzS/1MGlGmeJU54v6/UMWAs+6bCzOFUC1+uqU1KlzfmpsVG3MKxR4r/ZLZdxoKVfUuQMAA" + } + }, + "user_id": "@good:localhost" + }, + "ZGLCFWEPCY": { + "algorithms": [ + "m.olm.v1.curve25519-aes-sha2", + "m.megolm.v1.aes-sha2" + ], + "device_id": "ZGLCFWEPCY", + "keys": { + "curve25519:ZGLCFWEPCY": "kfcIEf6ZRgTP184yuIJYabfsBFsGXiVQE/cyW9qYnQA", + "ed25519:ZGLCFWEPCY": "WLSA1tSe0eOZCeESH5WMb9cp3AgRZzm4ooSud+NwcEw" + }, + "signatures": { + "@good:localhost": { + "ed25519:ZGLCFWEPCY": "AVXFgHk/QcAbOVBF5Xu4OW+03CZKBs2qAYh0fjIA49r+X+aX7QIKrbRyXU/ictPBLMpj1yXF+2J5vwR/KQYVCA", + "ed25519:YwQVBWn2sA5lLqp/dQsNk7fiYOuQuQhujefOPjejc+U": "VZk70FWiYN/YSwGykt2CygcOl1bq2D+dVSSKBL5GA5uHXxt6ypDlYvtWprM1l7re3llp5j105MevsjQ+2sWmCw" + } + }, + "user_id": "@good:localhost" + } + } + }, + "failures": {}, + "master_keys": { + "@good:localhost": { + "keys": { + "ed25519:5vTK2S2wVXo4xGT4BhcwpINVjRLjorkkJgCjnrHgtl8": "5vTK2S2wVXo4xGT4BhcwpINVjRLjorkkJgCjnrHgtl8" + }, + "signatures": { + "@good:localhost": { + "ed25519:5vTK2S2wVXo4xGT4BhcwpINVjRLjorkkJgCjnrHgtl8": "imAhrTIlPuf6hNqlbcSUnC2ndZPk5NwQLzbi9kZ8nmnPGjmv39f4U4Vh/KiweqQnI4ActGpcYyM7k9S2Ef8/CQ", + "ed25519:HPNYOQGUEE": "6w3egsvd+oVPCclef+hF1CfFMZrGTf/plFvPU5iP69WNw4w0UPAKSV1jOzh7Wv4LVGX5O3afjA9DG+O7aHZmBw" + } + }, + "usage": [ + "master" + ], + "user_id": "@good:localhost" + } + }, + "self_signing_keys": { + "@good:localhost": { + "keys": { + "ed25519:YwQVBWn2sA5lLqp/dQsNk7fiYOuQuQhujefOPjejc+U": "YwQVBWn2sA5lLqp/dQsNk7fiYOuQuQhujefOPjejc+U" + }, + "signatures": { + "@good:localhost": { + "ed25519:5vTK2S2wVXo4xGT4BhcwpINVjRLjorkkJgCjnrHgtl8": "2AyR8lovFv8J1DwPwdCsAM9Tw877QhaVHmVkPopsmSokS2fst8LDQtsg/PiftVc+74NGz5tnYIMDxn4BjAisAg" + } + }, + "usage": [ + "self_signing" + ], + "user_id": "@good:localhost" + } + }, + "user_signing_keys": { + "@good:localhost": { + "keys": { + "ed25519:u1PwO3/a/HTnN9IF7BVa2dJQ7bc00J22eNS0vM4FjTA": "u1PwO3/a/HTnN9IF7BVa2dJQ7bc00J22eNS0vM4FjTA" + }, + "signatures": { + "@good:localhost": { + "ed25519:5vTK2S2wVXo4xGT4BhcwpINVjRLjorkkJgCjnrHgtl8": "88v9/Z3TJeY2lsu3cFQaEuhHH5ixjJs22ALQRKY+O6VPGCT/BAzH6kUb7teinFfpvQjoXN3t5fVJxbP9mVlxDg" + } + }, + "usage": [ + "user_signing" + ], + "user_id": "@good:localhost" + } + } + }); + + let data = response_from_file(&data); + + KeyQueryResponse::try_from_http_response(data) + .expect("Can't parse the `/keys/upload` response") + } + + pub fn me_id() -> &'static UserId { + user_id!("@me:localhost") + } + + pub fn me_device_id() -> &'static DeviceId { + device_id!("ABCDEFGH") + } + + pub fn dan_unsigned_device_id() -> &'static DeviceId { + device_id!("FRGNMZVOKA") + } + + pub fn dan_signed_device_id() -> &'static DeviceId { + device_id!("JHPUERYQUW") + } + + pub fn dave_device_id() -> &'static DeviceId { + device_id!("HVCXJTHMBM") + } + + pub fn dan_id() -> &'static UserId { + user_id!("@dan:localhost") + } + + pub fn dave_id() -> &'static UserId { + user_id!("@dave:localhost") + } + + pub fn good_id() -> &'static UserId { + user_id!("@good:localhost") + } +} diff --git a/testing/matrix-sdk-test/src/test_json/mod.rs b/testing/matrix-sdk-test/src/test_json/mod.rs index 9c29bba81a1..beab57cc64e 100644 --- a/testing/matrix-sdk-test/src/test_json/mod.rs +++ b/testing/matrix-sdk-test/src/test_json/mod.rs @@ -10,6 +10,7 @@ use serde_json::{json, Value as JsonValue}; use crate::DEFAULT_TEST_ROOM_ID; pub mod api_responses; +pub mod keys_query_sets; pub mod members; pub mod search_users; pub mod sync;