crypto: Error when sending keys to previously-verified users with identity-based strategy (#3896)
This commit is contained in:
@@ -2,6 +2,16 @@
|
||||
|
||||
Breaking changes:
|
||||
|
||||
- `EventSendState` now has two additional variants: `CrossSigningNotSetup` and
|
||||
`SendingFromUnverifiedDevice`. These indicate that your own device is not
|
||||
properly cross-signed, which is a requirement when using the identity-based
|
||||
strategy, and can only be returned when using the identity-based strategy.
|
||||
|
||||
In addition, the `VerifiedUserHasUnsignedDevice` and
|
||||
`VerifiedUserChangedIdentity` variants can be returned when using the
|
||||
identity-based strategy, in addition to when using the device-based strategy
|
||||
with `error_on_verified_user_problem` is set.
|
||||
|
||||
- `EventSendState` now has two additional variants: `VerifiedUserHasUnsignedDevice` and
|
||||
`VerifiedUserChangedIdentity`. These reflect problems with verified users in the room
|
||||
and as such can only be returned when the room key recipient strategy has
|
||||
|
||||
@@ -929,12 +929,21 @@ pub enum EventSendState {
|
||||
///
|
||||
/// Happens only when the room key recipient strategy (as set by
|
||||
/// [`ClientBuilder::room_key_recipient_strategy`]) has
|
||||
/// [`error_on_verified_user_problem`](CollectStrategy::DeviceBasedStrategy::error_on_verified_user_problem) set.
|
||||
/// [`error_on_verified_user_problem`](CollectStrategy::DeviceBasedStrategy::error_on_verified_user_problem)
|
||||
/// set, or when using [`CollectStrategy::IdentityBasedStrategy`].
|
||||
VerifiedUserChangedIdentity {
|
||||
/// The users that were previously verified, but are no longer
|
||||
users: Vec<String>,
|
||||
},
|
||||
|
||||
/// The user does not have cross-signing set up, but
|
||||
/// [`CollectStrategy::IdentityBasedStrategy`] was used.
|
||||
CrossSigningNotSetup,
|
||||
|
||||
/// The current device is not verified, but
|
||||
/// [`CollectStrategy::IdentityBasedStrategy`] was used.
|
||||
SendingFromUnverifiedDevice,
|
||||
|
||||
/// The local event has been sent to the server, but unsuccessfully: The
|
||||
/// sending has failed.
|
||||
SendingFailed {
|
||||
@@ -988,6 +997,10 @@ fn event_send_state_from_sending_failed(error: &Error, is_recoverable: bool) ->
|
||||
VerifiedUserChangedIdentity(bad_users) => EventSendState::VerifiedUserChangedIdentity {
|
||||
users: bad_users.iter().map(|user_id| user_id.to_string()).collect(),
|
||||
},
|
||||
|
||||
CrossSigningNotSetup => EventSendState::CrossSigningNotSetup,
|
||||
|
||||
SendingFromUnverifiedDevice => EventSendState::SendingFromUnverifiedDevice,
|
||||
},
|
||||
|
||||
_ => EventSendState::SendingFailed { error: error.to_string(), is_recoverable },
|
||||
|
||||
@@ -56,6 +56,11 @@ Breaking changes:
|
||||
`OlmMachine::share_room_key` to fail with an error if any verified users on
|
||||
the recipient list have unsigned devices, or are no lonver verified.
|
||||
|
||||
When `CallectStrategy::IdentityBasedStrategy` is used,
|
||||
`OlmMachine::share_room_key` will fail with an error if any verified users on
|
||||
the recipient list are no longer verified, or if our own device is not
|
||||
properly cross-signed.
|
||||
|
||||
Also remove `CollectStrategy::new_device_based`: callers should construct a
|
||||
`CollectStrategy::DeviceBasedStrategy` directly.
|
||||
|
||||
@@ -63,6 +68,7 @@ Breaking changes:
|
||||
a list of booleans.
|
||||
([#3810](https://github.com/matrix-org/matrix-rust-sdk/pull/3810))
|
||||
([#3816](https://github.com/matrix-org/matrix-rust-sdk/pull/3816))
|
||||
([#3896](https://github.com/matrix-org/matrix-rust-sdk/pull/3896))
|
||||
|
||||
- Remove the method `OlmMachine::clear_crypto_cache()`, crypto stores are not
|
||||
supposed to have any caches anymore.
|
||||
|
||||
@@ -391,7 +391,7 @@ pub enum SessionRecipientCollectionError {
|
||||
///
|
||||
/// Happens only with [`CollectStrategy::DeviceBasedStrategy`] when
|
||||
/// [`error_on_verified_user_problem`](`CollectStrategy::DeviceBasedStrategy::error_on_verified_user_problem`)
|
||||
/// is true.
|
||||
/// is true, or with [`CollectStrategy::IdentityBasedStrategy`].
|
||||
///
|
||||
/// In order to resolve this, the user can:
|
||||
///
|
||||
@@ -407,4 +407,24 @@ pub enum SessionRecipientCollectionError {
|
||||
/// The caller can then retry the encryption operation.
|
||||
#[error("one or more users that were verified have changed their identity")]
|
||||
VerifiedUserChangedIdentity(Vec<OwnedUserId>),
|
||||
|
||||
/// Cross-signing has not been configured on our own identity.
|
||||
///
|
||||
/// Happens only with [`CollectStrategy::IdentityBasedStrategy`].
|
||||
/// (Cross-signing is required for encryption when using
|
||||
/// `IdentityBasedStrategy`.) Apps should detect this condition and prevent
|
||||
/// sending in the UI rather than waiting for this error to be returned when
|
||||
/// encrypting.
|
||||
#[error("Encryption failed because cross-signing is not set up on your account")]
|
||||
CrossSigningNotSetup,
|
||||
|
||||
/// The current device has not been cross-signed by our own identity.
|
||||
///
|
||||
/// Happens only with [`CollectStrategy::IdentityBasedStrategy`].
|
||||
/// (Cross-signing is required for encryption when using
|
||||
/// `IdentityBasedStrategy`.) Apps should detect this condition and prevent
|
||||
/// sending in the UI rather than waiting for this error to be returned when
|
||||
/// encrypting.
|
||||
#[error("Encryption failed because your device is not verified")]
|
||||
SendingFromUnverifiedDevice,
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ pub(crate) async fn collect_session_recipients(
|
||||
let users: BTreeSet<&UserId> = users.collect();
|
||||
let mut devices: BTreeMap<OwnedUserId, Vec<DeviceData>> = Default::default();
|
||||
let mut withheld_devices: Vec<(DeviceData, WithheldCode)> = Default::default();
|
||||
let mut verified_users_with_new_identities: Vec<OwnedUserId> = Default::default();
|
||||
|
||||
trace!(?users, ?settings, "Calculating group session recipients");
|
||||
|
||||
@@ -145,6 +146,8 @@ pub(crate) async fn collect_session_recipients(
|
||||
// This is calculated in the following code and stored in this variable.
|
||||
let mut should_rotate = user_left || visibility_changed || algorithm_changed;
|
||||
|
||||
let own_identity = store.get_user_identity(store.user_id()).await?.and_then(|i| i.into_own());
|
||||
|
||||
// Get the recipient and withheld devices, based on the collection strategy.
|
||||
match settings.sharing_strategy {
|
||||
CollectStrategy::DeviceBasedStrategy {
|
||||
@@ -153,10 +156,6 @@ pub(crate) async fn collect_session_recipients(
|
||||
} => {
|
||||
let mut unsigned_devices_of_verified_users: BTreeMap<OwnedUserId, Vec<OwnedDeviceId>> =
|
||||
Default::default();
|
||||
let mut verified_users_with_new_identities: Vec<OwnedUserId> = Default::default();
|
||||
|
||||
let own_identity =
|
||||
store.get_user_identity(store.user_id()).await?.and_then(|i| i.into_own());
|
||||
|
||||
for user_id in users {
|
||||
trace!("Considering recipient devices for user {}", user_id);
|
||||
@@ -233,24 +232,39 @@ pub(crate) async fn collect_session_recipients(
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
// Alternatively, we may have encountered previously-verified users who have
|
||||
// changed their identities. We bail out for that, too.
|
||||
if !verified_users_with_new_identities.is_empty() {
|
||||
return Err(OlmError::SessionRecipientCollectionError(
|
||||
SessionRecipientCollectionError::VerifiedUserChangedIdentity(
|
||||
verified_users_with_new_identities,
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
CollectStrategy::IdentityBasedStrategy => {
|
||||
// We require our own cross-signing to be properly set up for the
|
||||
// identity-based strategy, so return an error if it isn't.
|
||||
match &own_identity {
|
||||
None => {
|
||||
return Err(OlmError::SessionRecipientCollectionError(
|
||||
SessionRecipientCollectionError::CrossSigningNotSetup,
|
||||
))
|
||||
}
|
||||
Some(identity) if !identity.is_verified() => {
|
||||
return Err(OlmError::SessionRecipientCollectionError(
|
||||
SessionRecipientCollectionError::SendingFromUnverifiedDevice,
|
||||
))
|
||||
}
|
||||
Some(_) => (),
|
||||
}
|
||||
|
||||
for user_id in users {
|
||||
trace!("Considering recipient devices for user {}", user_id);
|
||||
let user_devices = store.get_device_data_for_user_filtered(user_id).await?;
|
||||
|
||||
let device_owner_identity = store.get_user_identity(user_id).await?;
|
||||
|
||||
if has_identity_verification_violation(
|
||||
own_identity.as_ref(),
|
||||
device_owner_identity.as_ref(),
|
||||
) {
|
||||
verified_users_with_new_identities.push(user_id.to_owned());
|
||||
// No point considering the individual devices of this user.
|
||||
continue;
|
||||
}
|
||||
|
||||
let recipient_devices = split_recipients_withhelds_for_user_based_on_identity(
|
||||
user_devices,
|
||||
&device_owner_identity,
|
||||
@@ -277,6 +291,16 @@ pub(crate) async fn collect_session_recipients(
|
||||
}
|
||||
}
|
||||
|
||||
// We may have encountered previously-verified users who have changed their
|
||||
// identities. If so, we bail out with an error.
|
||||
if !verified_users_with_new_identities.is_empty() {
|
||||
return Err(OlmError::SessionRecipientCollectionError(
|
||||
SessionRecipientCollectionError::VerifiedUserChangedIdentity(
|
||||
verified_users_with_new_identities,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
if should_rotate {
|
||||
debug!(
|
||||
should_rotate,
|
||||
@@ -491,10 +515,14 @@ fn is_user_verified(
|
||||
mod tests {
|
||||
use std::{collections::BTreeMap, iter, sync::Arc};
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use assert_matches2::assert_let;
|
||||
use matrix_sdk_test::{
|
||||
async_test, test_json,
|
||||
test_json::keys_query_sets::{KeyDistributionTestData, PreviouslyVerifiedTestData},
|
||||
test_json::keys_query_sets::{
|
||||
IdentityChangeDataSet, KeyDistributionTestData, MaloIdentityChangeDataSet,
|
||||
PreviouslyVerifiedTestData,
|
||||
},
|
||||
};
|
||||
use ruma::{
|
||||
device_id, events::room::history_visibility::HistoryVisibility, room_id, TransactionId,
|
||||
@@ -1122,6 +1150,249 @@ mod tests {
|
||||
assert_eq!(code, &WithheldCode::Unauthorised);
|
||||
}
|
||||
|
||||
/// Test key sharing with the identity-based strategy with different
|
||||
/// states of our own verification.
|
||||
#[async_test]
|
||||
async fn test_share_identity_strategy_no_cross_signing() {
|
||||
// Starting off, we have not yet set up our own cross-signing, so
|
||||
// sharing with the identity-based strategy should fail.
|
||||
let machine: OlmMachine = OlmMachine::new(
|
||||
KeyDistributionTestData::me_id(),
|
||||
KeyDistributionTestData::me_device_id(),
|
||||
)
|
||||
.await;
|
||||
|
||||
let keys_query = KeyDistributionTestData::dan_keys_query_response();
|
||||
machine.mark_request_as_sent(&TransactionId::new(), &keys_query).await.unwrap();
|
||||
|
||||
let fake_room_id = room_id!("!roomid:localhost");
|
||||
|
||||
let encryption_settings = EncryptionSettings {
|
||||
sharing_strategy: CollectStrategy::new_identity_based(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let request_result = machine
|
||||
.share_room_key(
|
||||
fake_room_id,
|
||||
iter::once(KeyDistributionTestData::dan_id()),
|
||||
encryption_settings.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_matches!(
|
||||
request_result,
|
||||
Err(OlmError::SessionRecipientCollectionError(
|
||||
SessionRecipientCollectionError::CrossSigningNotSetup
|
||||
))
|
||||
);
|
||||
|
||||
// We now get our public cross-signing keys, but we don't trust them
|
||||
// yet. In this case, sharing the keys should still fail since our own
|
||||
// device is still unverified.
|
||||
let keys_query = KeyDistributionTestData::me_keys_query_response();
|
||||
machine.mark_request_as_sent(&TransactionId::new(), &keys_query).await.unwrap();
|
||||
|
||||
let request_result = machine
|
||||
.share_room_key(
|
||||
fake_room_id,
|
||||
iter::once(KeyDistributionTestData::dan_id()),
|
||||
encryption_settings.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_matches!(
|
||||
request_result,
|
||||
Err(OlmError::SessionRecipientCollectionError(
|
||||
SessionRecipientCollectionError::SendingFromUnverifiedDevice
|
||||
))
|
||||
);
|
||||
|
||||
// Finally, after we trust our own cross-signing keys, key sharing
|
||||
// should succeed.
|
||||
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 requests = machine
|
||||
.share_room_key(
|
||||
fake_room_id,
|
||||
iter::once(KeyDistributionTestData::dan_id()),
|
||||
encryption_settings.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Dan has two devices, but only one is cross-signed, so there should
|
||||
// only be one key share.
|
||||
assert_eq!(requests.len(), 1);
|
||||
}
|
||||
|
||||
/// Test that identity-based key sharing gives an error when a verified
|
||||
/// user changes their identity, and that the key can be shared when the
|
||||
/// identity change is resolved.
|
||||
#[async_test]
|
||||
async fn test_share_identity_strategy_report_verification_violation() {
|
||||
let machine: OlmMachine = OlmMachine::new(
|
||||
KeyDistributionTestData::me_id(),
|
||||
KeyDistributionTestData::me_device_id(),
|
||||
)
|
||||
.await;
|
||||
|
||||
machine.bootstrap_cross_signing(false).await.unwrap();
|
||||
|
||||
// We will try sending a key to two different users.
|
||||
let user1 = IdentityChangeDataSet::user_id();
|
||||
let user2 = MaloIdentityChangeDataSet::user_id();
|
||||
|
||||
// We first get both users' initial device and identity keys.
|
||||
let keys_query = IdentityChangeDataSet::key_query_with_identity_a();
|
||||
machine.mark_request_as_sent(&TransactionId::new(), &keys_query).await.unwrap();
|
||||
|
||||
let keys_query = MaloIdentityChangeDataSet::initial_key_query();
|
||||
machine.mark_request_as_sent(&TransactionId::new(), &keys_query).await.unwrap();
|
||||
|
||||
// And then we get both user' changed identity keys. We simulate a
|
||||
// verification violation by marking both users as having been
|
||||
// previously verified, in which case the key sharing should fail.
|
||||
let keys_query = IdentityChangeDataSet::key_query_with_identity_b();
|
||||
machine.mark_request_as_sent(&TransactionId::new(), &keys_query).await.unwrap();
|
||||
machine
|
||||
.get_identity(user1, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.other()
|
||||
.unwrap()
|
||||
.mark_as_previously_verified()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let keys_query = MaloIdentityChangeDataSet::updated_key_query();
|
||||
machine.mark_request_as_sent(&TransactionId::new(), &keys_query).await.unwrap();
|
||||
machine
|
||||
.get_identity(user2, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.other()
|
||||
.unwrap()
|
||||
.mark_as_previously_verified()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let fake_room_id = room_id!("!roomid:localhost");
|
||||
|
||||
// We share the key using the identity-based strategy.
|
||||
let encryption_settings = EncryptionSettings {
|
||||
sharing_strategy: CollectStrategy::new_identity_based(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let request_result = machine
|
||||
.share_room_key(
|
||||
fake_room_id,
|
||||
vec![user1, user2].into_iter(),
|
||||
encryption_settings.clone(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// The key share should fail with an error indicating that recipients
|
||||
// were previously verified.
|
||||
assert_let!(
|
||||
Err(OlmError::SessionRecipientCollectionError(
|
||||
SessionRecipientCollectionError::VerifiedUserChangedIdentity(affected_users)
|
||||
)) = request_result
|
||||
);
|
||||
// Both our recipients should be in `affected_users`.
|
||||
assert_eq!(2, affected_users.len());
|
||||
|
||||
// We resolve this for user1 by withdrawing their verification.
|
||||
machine
|
||||
.get_identity(user1, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.withdraw_verification()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// We resolve this for user2 by re-verifying.
|
||||
let verification_request = machine
|
||||
.get_identity(user2, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.other()
|
||||
.unwrap()
|
||||
.verify()
|
||||
.await
|
||||
.unwrap();
|
||||
let raw_extracted =
|
||||
verification_request.signed_keys.get(user2).unwrap().iter().next().unwrap().1.get();
|
||||
let signed_key: crate::types::CrossSigningKey =
|
||||
serde_json::from_str(raw_extracted).unwrap();
|
||||
let new_signatures = signed_key.signatures.get(KeyDistributionTestData::me_id()).unwrap();
|
||||
let mut master_key = machine
|
||||
.get_identity(user2, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.other()
|
||||
.unwrap()
|
||||
.master_key
|
||||
.as_ref()
|
||||
.clone();
|
||||
|
||||
for (key_id, signature) in new_signatures.iter() {
|
||||
master_key.as_mut().signatures.add_signature(
|
||||
KeyDistributionTestData::me_id().to_owned(),
|
||||
key_id.to_owned(),
|
||||
signature.as_ref().unwrap().ed25519().unwrap(),
|
||||
);
|
||||
}
|
||||
let json = serde_json::json!({
|
||||
"device_keys": {},
|
||||
"failures": {},
|
||||
"master_keys": {
|
||||
user2: master_key,
|
||||
},
|
||||
"user_signing_keys": {},
|
||||
"self_signing_keys": MaloIdentityChangeDataSet::updated_key_query().self_signing_keys,
|
||||
}
|
||||
);
|
||||
|
||||
let kq_response = matrix_sdk_test::ruma_response_from_json(&json);
|
||||
machine
|
||||
.mark_request_as_sent(
|
||||
&TransactionId::new(),
|
||||
crate::IncomingResponse::KeysQuery(&kq_response),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(machine.get_identity(user2, None).await.unwrap().unwrap().is_verified());
|
||||
|
||||
// And now the key share should succeed.
|
||||
machine
|
||||
.share_room_key(
|
||||
fake_room_id,
|
||||
vec![user1, user2].into_iter(),
|
||||
encryption_settings.clone(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_should_rotate_based_on_visibility() {
|
||||
let machine = set_up_test_machine().await;
|
||||
|
||||
@@ -1263,3 +1263,151 @@ impl PreviouslyVerifiedTestData {
|
||||
ruma_response_from_json(&data)
|
||||
}
|
||||
}
|
||||
|
||||
/// A set of keys query to test identity changes,
|
||||
/// For user @malo, that performed an identity change with the same device.
|
||||
pub struct MaloIdentityChangeDataSet {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl MaloIdentityChangeDataSet {
|
||||
pub fn user_id() -> &'static UserId {
|
||||
user_id!("@malo:localhost")
|
||||
}
|
||||
|
||||
pub fn device_id() -> &'static DeviceId {
|
||||
device_id!("NZFSPBRLDO")
|
||||
}
|
||||
|
||||
/// @malo's keys before their identity change
|
||||
pub fn initial_key_query() -> KeyQueryResponse {
|
||||
let data = json!({
|
||||
"device_keys": {
|
||||
"@malo:localhost": {
|
||||
"NZFSPBRLDO": {
|
||||
"algorithms": [
|
||||
"m.olm.v1.curve25519-aes-sha2",
|
||||
"m.megolm.v1.aes-sha2"
|
||||
],
|
||||
"device_id": "NZFSPBRLDO",
|
||||
"keys": {
|
||||
"curve25519:NZFSPBRLDO": "L3jdbw42+9i+K7LPjAY+kmqG9nr2n/U0ow8hEbLCoCs",
|
||||
"ed25519:NZFSPBRLDO": "VDJt3xI4SzrgQkuE3sEIauluaXawx3wWoWOynPI8Zko"
|
||||
},
|
||||
"signatures": {
|
||||
"@malo:localhost": {
|
||||
"ed25519:NZFSPBRLDO": "lmtbdrJ5xBweo677Fg2qrSHsRi4R3x2WNlvSNJY6Zbg0R5lJS9syN2HZw/irL9PA644GYm4QM/t+DX0grnn+BQ",
|
||||
"ed25519:+wbxNfSuDrch1jKuydQmEf4qlA4u4NgwqNXNuLVwug8": "Ql1fq+SvVDx+8mjNMzSaR0hBCEkdPirbs2+BK0gwsIH1zkuMADnBoNWP7LJiKo/EO9gnpiCzyQQgI4e9pIVPDA"
|
||||
}
|
||||
},
|
||||
"user_id": "@malo:localhost",
|
||||
"unsigned": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"failures": {},
|
||||
"master_keys": {
|
||||
"@malo:localhost": {
|
||||
"keys": {
|
||||
"ed25519:WBxliSP29guYr4ux0MW6otRe3V/wOLXXElpOcOmpdlE": "WBxliSP29guYr4ux0MW6otRe3V/wOLXXElpOcOmpdlE"
|
||||
},
|
||||
"signatures": {
|
||||
"@malo:localhost": {
|
||||
"ed25519:NZFSPBRLDO": "crJcXqFpEHRM8KNUw419XrVFaHoM8/kV4ebgpuuIiD9wfX0AhHE2iGRGpKzsrVCqne9k181/uN0sgDMpK2y4Aw",
|
||||
"ed25519:WBxliSP29guYr4ux0MW6otRe3V/wOLXXElpOcOmpdlE": "/xwFF5AC3GhkpvJ449Srh8kNQS6CXAxQMmBpQvPEHx5BHPXJ08u2ZDd1EPYY4zk4QsePk+tEYu8gDnB0bggHCA"
|
||||
}
|
||||
},
|
||||
"usage": [
|
||||
"master"
|
||||
],
|
||||
"user_id": "@malo:localhost"
|
||||
}
|
||||
},
|
||||
"self_signing_keys": {
|
||||
"@malo:localhost": {
|
||||
"keys": {
|
||||
"ed25519:+wbxNfSuDrch1jKuydQmEf4qlA4u4NgwqNXNuLVwug8": "+wbxNfSuDrch1jKuydQmEf4qlA4u4NgwqNXNuLVwug8"
|
||||
},
|
||||
"signatures": {
|
||||
"@malo:localhost": {
|
||||
"ed25519:WBxliSP29guYr4ux0MW6otRe3V/wOLXXElpOcOmpdlE": "sSGQ6ny6aXtIvgKPGOYJzcmnNDSkbaJFVRe9wekOry7EaiWf2l28MkGTUBt4cPoRiMkNjuRBupNEARqHF72sAQ"
|
||||
}
|
||||
},
|
||||
"usage": [
|
||||
"self_signing"
|
||||
],
|
||||
"user_id": "@malo:localhost"
|
||||
}
|
||||
},
|
||||
"user_signing_keys": {},
|
||||
});
|
||||
|
||||
ruma_response_from_json(&data)
|
||||
}
|
||||
|
||||
/// @malo's keys after their identity change
|
||||
pub fn updated_key_query() -> KeyQueryResponse {
|
||||
let data = json!({
|
||||
"device_keys": {
|
||||
"@malo:localhost": {
|
||||
"NZFSPBRLDO": {
|
||||
"algorithms": [
|
||||
"m.olm.v1.curve25519-aes-sha2",
|
||||
"m.megolm.v1.aes-sha2"
|
||||
],
|
||||
"device_id": "NZFSPBRLDO",
|
||||
"keys": {
|
||||
"curve25519:NZFSPBRLDO": "L3jdbw42+9i+K7LPjAY+kmqG9nr2n/U0ow8hEbLCoCs",
|
||||
"ed25519:NZFSPBRLDO": "VDJt3xI4SzrgQkuE3sEIauluaXawx3wWoWOynPI8Zko"
|
||||
},
|
||||
"signatures": {
|
||||
"@malo:localhost": {
|
||||
"ed25519:NZFSPBRLDO": "lmtbdrJ5xBweo677Fg2qrSHsRi4R3x2WNlvSNJY6Zbg0R5lJS9syN2HZw/irL9PA644GYm4QM/t+DX0grnn+BQ",
|
||||
"ed25519:+wbxNfSuDrch1jKuydQmEf4qlA4u4NgwqNXNuLVwug8": "Ql1fq+SvVDx+8mjNMzSaR0hBCEkdPirbs2+BK0gwsIH1zkuMADnBoNWP7LJiKo/EO9gnpiCzyQQgI4e9pIVPDA",
|
||||
"ed25519:8my6+zgnzEP0ZqmQFyvscJh7isHlf8lxBmHg+fzdJkE": "OvqDE7C2mrHxjwNyMIEz+m/AO6I6lM5HoPYY2bvLjrJJDOF5sJOtw4JoYiCWyt90ZIWsbEqmfbazrblLD50tCg"
|
||||
}
|
||||
},
|
||||
"user_id": "@malo:localhost",
|
||||
"unsigned": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"failures": {},
|
||||
"master_keys": {
|
||||
"@malo:localhost": {
|
||||
"keys": {
|
||||
"ed25519:dv2Mk7bFlRtP/0oSZpB01Ouc5frCXKfG8Bn9YrFxbxU": "dv2Mk7bFlRtP/0oSZpB01Ouc5frCXKfG8Bn9YrFxbxU"
|
||||
},
|
||||
"signatures": {
|
||||
"@malo:localhost": {
|
||||
"ed25519:NZFSPBRLDO": "2Ye96l4srBSWskNQszuMpea1r97rFoUyfNqegvu/hGeP47w0OVvqYuNtZRNwqb7TMS7aPEn6l9lhWEk7v06wCg",
|
||||
"ed25519:dv2Mk7bFlRtP/0oSZpB01Ouc5frCXKfG8Bn9YrFxbxU": "btkxAJpJeVtc9wgBmeHUI9QDpojd6ddLxK11E3403KoTQtP6Mnr5GsVdQr1HJToG7PG4k4eEZGWxVZr1GPndAA"
|
||||
}
|
||||
},
|
||||
"usage": [
|
||||
"master"
|
||||
],
|
||||
"user_id": "@malo:localhost"
|
||||
}
|
||||
},
|
||||
"self_signing_keys": {
|
||||
"@malo:localhost": {
|
||||
"keys": {
|
||||
"ed25519:8my6+zgnzEP0ZqmQFyvscJh7isHlf8lxBmHg+fzdJkE": "8my6+zgnzEP0ZqmQFyvscJh7isHlf8lxBmHg+fzdJkE"
|
||||
},
|
||||
"signatures": {
|
||||
"@malo:localhost": {
|
||||
"ed25519:dv2Mk7bFlRtP/0oSZpB01Ouc5frCXKfG8Bn9YrFxbxU": "KJt0y1p8v8RGLGk2wUyCMbX1irXJqup/mdRuG/cxJxs24BZhDMyIzyGrGXnWq2gx3I4fKIMtFPi/ecxf92ePAQ"
|
||||
}
|
||||
},
|
||||
"usage": [
|
||||
"self_signing"
|
||||
],
|
||||
"user_id": "@malo:localhost"
|
||||
}
|
||||
},
|
||||
"user_signing_keys": {}
|
||||
});
|
||||
|
||||
ruma_response_from_json(&data)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user