mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-08 16:04:13 -04:00
Add a dehydrated flag to device_keys of dehydrated devices (#3164)
Signed-off-by: Hubert Chathi <hubert@uhoreg.ca> Co-authored-by: Damir Jelić <poljar@termina.org.uk>
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -3115,6 +3115,7 @@ dependencies = [
|
||||
"http",
|
||||
"indoc",
|
||||
"itertools 0.12.1",
|
||||
"js_option",
|
||||
"matrix-sdk-common",
|
||||
"matrix-sdk-qrcode",
|
||||
"matrix-sdk-test",
|
||||
|
||||
@@ -243,6 +243,7 @@ async fn migrate_data(
|
||||
user_id: parse_user_id(&data.account.user_id)?,
|
||||
device_id: device_id.clone(),
|
||||
pickle,
|
||||
dehydrated: false, // dehydrated devices are never involved in migration
|
||||
shared: data.account.shared,
|
||||
uploaded_signed_key_count: data.account.uploaded_signed_key_count as u64,
|
||||
creation_local_time: MilliSecondsSinceUnixEpoch::now(),
|
||||
|
||||
@@ -14,6 +14,9 @@ Breaking changes:
|
||||
- Move `OlmMachine::export_room_keys` to `matrix_sdk_crypto::store::Store`.
|
||||
(Call it with `olm_machine.store().export_room_keys(...)`.)
|
||||
|
||||
- Add new `dehydrated` property to `olm::account::PickledAccount`.
|
||||
([#3164](https://github.com/matrix-org/matrix-rust-sdk/pull/3164))
|
||||
|
||||
Additions:
|
||||
|
||||
- When Olm message decryption fails, report the error code(s) from the failure.
|
||||
|
||||
@@ -43,6 +43,7 @@ hkdf = "0.12.3"
|
||||
hmac = "0.12.1"
|
||||
http = { workspace = true, optional = true } # feature = testing only
|
||||
itertools = { workspace = true }
|
||||
js_option = "0.1.1"
|
||||
matrix-sdk-qrcode = { workspace = true, optional = true }
|
||||
matrix-sdk-common = { workspace = true }
|
||||
pbkdf2 = { version = "0.12.2", default-features = false }
|
||||
|
||||
@@ -95,7 +95,7 @@ impl DehydratedDevices {
|
||||
let user_id = self.inner.user_id();
|
||||
let user_identity = self.inner.store().private_identity();
|
||||
|
||||
let account = Account::new(user_id);
|
||||
let account = Account::new_dehydrated(user_id);
|
||||
let store = Arc::new(CryptoStoreWrapper::new(user_id, MemoryStore::new()));
|
||||
|
||||
let verification_machine = VerificationMachine::new(
|
||||
@@ -378,6 +378,7 @@ fn expand_pickle_key(key: &[u8; 32], device_id: &DeviceId) -> Box<[u8; 32]> {
|
||||
mod tests {
|
||||
use std::{collections::BTreeMap, iter};
|
||||
|
||||
use js_option::JsOption;
|
||||
use matrix_sdk_test::async_test;
|
||||
use ruma::{
|
||||
api::client::keys::get_keys::v3::Response as KeysQueryResponse, assign,
|
||||
@@ -390,7 +391,7 @@ mod tests {
|
||||
create_session, get_prepared_machine_test_helper, to_device_requests_to_content,
|
||||
},
|
||||
olm::OutboundGroupSession,
|
||||
types::events::ToDeviceEvent,
|
||||
types::{events::ToDeviceEvent, DeviceKeys as DeviceKeysType},
|
||||
utilities::json_convert,
|
||||
EncryptionSettings, OlmMachine,
|
||||
};
|
||||
@@ -477,6 +478,13 @@ mod tests {
|
||||
!request.fallback_keys.is_empty(),
|
||||
"The dehydrated device creation request should contain some fallback keys"
|
||||
);
|
||||
|
||||
let device_keys: DeviceKeysType = request.device_keys.deserialize_as().unwrap();
|
||||
assert_eq!(
|
||||
device_keys.dehydrated,
|
||||
JsOption::Some(true),
|
||||
"The device keys of the dehydrated device should be marked as dehydrated."
|
||||
);
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
|
||||
@@ -481,6 +481,11 @@ impl Device {
|
||||
|
||||
Ok(raw_encrypted)
|
||||
}
|
||||
|
||||
/// Whether or not the device is a dehydrated device.
|
||||
pub fn is_dehydrated(&self) -> bool {
|
||||
self.inner.inner.dehydrated.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// A read only view over all devices belonging to a user.
|
||||
|
||||
@@ -20,6 +20,7 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use js_option::JsOption;
|
||||
use ruma::{
|
||||
api::client::{
|
||||
dehydrated_device::{DehydratedDeviceData, DehydratedDeviceV1},
|
||||
@@ -162,6 +163,8 @@ pub struct StaticAccountData {
|
||||
pub device_id: OwnedDeviceId,
|
||||
/// The associated identity keys.
|
||||
pub identity_keys: Arc<IdentityKeys>,
|
||||
/// Whether the account is for a dehydrated device.
|
||||
pub dehydrated: bool,
|
||||
// The creation time of the account in milliseconds since epoch.
|
||||
creation_local_time: MilliSecondsSinceUnixEpoch,
|
||||
}
|
||||
@@ -282,13 +285,17 @@ impl StaticAccountData {
|
||||
),
|
||||
]);
|
||||
|
||||
DeviceKeys::new(
|
||||
let mut ret = DeviceKeys::new(
|
||||
(*self.user_id).to_owned(),
|
||||
(*self.device_id).to_owned(),
|
||||
Self::ALGORITHMS.iter().map(|a| (**a).clone()).collect(),
|
||||
keys,
|
||||
Default::default(),
|
||||
)
|
||||
);
|
||||
if self.dehydrated {
|
||||
ret.dehydrated = JsOption::Some(true);
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
/// Get the user id of the owner of the account.
|
||||
@@ -361,6 +368,9 @@ pub struct PickledAccount {
|
||||
pub pickle: AccountPickle,
|
||||
/// Was the account shared.
|
||||
pub shared: bool,
|
||||
/// Whether this is for a dehydrated device
|
||||
#[serde(default)]
|
||||
pub dehydrated: bool,
|
||||
/// The number of uploaded one-time keys we have on the server.
|
||||
pub uploaded_signed_key_count: u64,
|
||||
/// The local time creation of this account (milliseconds since epoch), used
|
||||
@@ -411,6 +421,7 @@ impl Account {
|
||||
user_id: user_id.into(),
|
||||
device_id: device_id.into(),
|
||||
identity_keys: Arc::new(identity_keys),
|
||||
dehydrated: false,
|
||||
creation_local_time: MilliSecondsSinceUnixEpoch::now(),
|
||||
},
|
||||
inner: Box::new(account),
|
||||
@@ -437,6 +448,17 @@ impl Account {
|
||||
Self::new_helper(account, user_id, &device_id)
|
||||
}
|
||||
|
||||
/// Create a new random Olm Account for a dehydrated device
|
||||
pub fn new_dehydrated(user_id: &UserId) -> Self {
|
||||
let account = InnerAccount::new();
|
||||
let device_id: OwnedDeviceId =
|
||||
base64_encode(account.identity_keys().curve25519.as_bytes()).into();
|
||||
|
||||
let mut ret = Self::new_helper(account, user_id, &device_id);
|
||||
ret.static_data.dehydrated = true;
|
||||
ret
|
||||
}
|
||||
|
||||
/// Get the immutable data for this account.
|
||||
pub fn static_data(&self) -> &StaticAccountData {
|
||||
&self.static_data
|
||||
@@ -650,6 +672,7 @@ impl Account {
|
||||
device_id: self.device_id().to_owned(),
|
||||
pickle,
|
||||
shared: self.shared(),
|
||||
dehydrated: self.static_data.dehydrated,
|
||||
uploaded_signed_key_count: self.uploaded_key_count(),
|
||||
creation_local_time: self.static_data.creation_local_time,
|
||||
fallback_key_creation_timestamp: self.fallback_creation_timestamp,
|
||||
@@ -704,6 +727,7 @@ impl Account {
|
||||
user_id: (*pickle.user_id).into(),
|
||||
device_id: (*pickle.device_id).into(),
|
||||
identity_keys: Arc::new(identity_keys),
|
||||
dehydrated: pickle.dehydrated,
|
||||
creation_local_time: pickle.creation_local_time,
|
||||
},
|
||||
inner: Box::new(account),
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use js_option::JsOption;
|
||||
use ruma::{
|
||||
serde::Raw, DeviceKeyAlgorithm, DeviceKeyId, OwnedDeviceId, OwnedDeviceKeyId, OwnedUserId,
|
||||
};
|
||||
@@ -52,6 +53,10 @@ pub struct DeviceKeys {
|
||||
/// Signatures for the device key object.
|
||||
pub signatures: Signatures,
|
||||
|
||||
/// Whether the device is a dehydrated device or not
|
||||
#[serde(default, skip_serializing_if = "JsOption::is_undefined")]
|
||||
pub dehydrated: JsOption<bool>,
|
||||
|
||||
/// Additional data added to the device key information by intermediate
|
||||
/// servers, and not covered by the signatures.
|
||||
#[serde(default, skip_serializing_if = "UnsignedDeviceInfo::is_empty")]
|
||||
@@ -77,6 +82,7 @@ impl DeviceKeys {
|
||||
algorithms,
|
||||
keys,
|
||||
signatures,
|
||||
dehydrated: JsOption::Undefined,
|
||||
unsigned: Default::default(),
|
||||
other: BTreeMap::new(),
|
||||
}
|
||||
@@ -182,6 +188,8 @@ struct DeviceKeyHelper {
|
||||
pub device_id: OwnedDeviceId,
|
||||
pub algorithms: Vec<EventEncryptionAlgorithm>,
|
||||
pub keys: BTreeMap<OwnedDeviceKeyId, String>,
|
||||
#[serde(default, skip_serializing_if = "JsOption::is_undefined")]
|
||||
pub dehydrated: JsOption<bool>,
|
||||
pub signatures: Signatures,
|
||||
#[serde(default, skip_serializing_if = "UnsignedDeviceInfo::is_empty")]
|
||||
pub unsigned: UnsignedDeviceInfo,
|
||||
@@ -216,6 +224,7 @@ impl TryFrom<DeviceKeyHelper> for DeviceKeys {
|
||||
device_id: value.device_id,
|
||||
algorithms: value.algorithms,
|
||||
keys: keys?,
|
||||
dehydrated: value.dehydrated,
|
||||
signatures: value.signatures,
|
||||
unsigned: value.unsigned,
|
||||
other: value.other,
|
||||
@@ -233,6 +242,7 @@ impl From<DeviceKeys> for DeviceKeyHelper {
|
||||
device_id: value.device_id,
|
||||
algorithms: value.algorithms,
|
||||
keys,
|
||||
dehydrated: value.dehydrated,
|
||||
signatures: value.signatures,
|
||||
unsigned: value.unsigned,
|
||||
other: value.other,
|
||||
|
||||
Reference in New Issue
Block a user