mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-11 09:23:23 -04:00
Add a message id to our encrypted to-device events
This commit is contained in:
10
Cargo.lock
generated
10
Cargo.lock
generated
@@ -2713,6 +2713,7 @@ dependencies = [
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"ulid",
|
||||
"vodozemac",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -5440,6 +5441,15 @@ version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "ulid"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13a3aaa69b04e5b66cc27309710a569ea23593612387d67daaf102e73aa974fd"
|
||||
dependencies = [
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unarray"
|
||||
version = "0.1.4"
|
||||
|
||||
@@ -46,6 +46,7 @@ version = "0.6.0"
|
||||
[dependencies.matrix-sdk-crypto]
|
||||
path = "../../crates/matrix-sdk-crypto"
|
||||
version = "0.6.0"
|
||||
default_features = false
|
||||
features = ["qrcode", "backups_v1", "automatic-room-key-forwarding"]
|
||||
|
||||
[dependencies.matrix-sdk-sqlite]
|
||||
|
||||
@@ -41,7 +41,6 @@ futures-util = "0.3.27"
|
||||
http = { workspace = true }
|
||||
js-sys = "0.3.49"
|
||||
matrix-sdk-common = { version = "0.6.0", path = "../../crates/matrix-sdk-common", features = ["js"] }
|
||||
matrix-sdk-crypto = { version = "0.6.0", path = "../../crates/matrix-sdk-crypto", features = ["js", "automatic-room-key-forwarding"] }
|
||||
matrix-sdk-indexeddb = { version = "0.2.0", path = "../../crates/matrix-sdk-indexeddb" }
|
||||
matrix-sdk-qrcode = { version = "0.4.0", path = "../../crates/matrix-sdk-qrcode", optional = true }
|
||||
ruma = { workspace = true, features = ["js", "rand", "unstable-msc2677"] }
|
||||
@@ -52,3 +51,9 @@ vodozemac = { workspace = true, features = ["js"] }
|
||||
wasm-bindgen = "0.2.83"
|
||||
wasm-bindgen-futures = "0.4.33"
|
||||
zeroize = { workspace = true }
|
||||
|
||||
[dependencies.matrix-sdk-crypto]
|
||||
path = "../../crates/matrix-sdk-crypto"
|
||||
version = "0.6.0"
|
||||
default_features = false
|
||||
features = ["js", "automatic-room-key-forwarding"]
|
||||
|
||||
@@ -24,7 +24,6 @@ qrcode = ["matrix-sdk-crypto/qrcode"]
|
||||
tracing = ["dep:tracing-subscriber"]
|
||||
|
||||
[dependencies]
|
||||
matrix-sdk-crypto = { version = "0.6.0", path = "../../crates/matrix-sdk-crypto", features = ["js", "automatic-room-key-forwarding"] }
|
||||
matrix-sdk-common = { version = "0.6.0", path = "../../crates/matrix-sdk-common", features = ["js"] }
|
||||
matrix-sdk-sled = { version = "0.2.0", path = "../../crates/matrix-sdk-sled", default-features = false, features = ["crypto-store"] }
|
||||
matrix-sdk-sqlite = { version = "0.1.0", path = "../../crates/matrix-sdk-sqlite", features = ["crypto-store"] }
|
||||
@@ -37,5 +36,11 @@ tracing-subscriber = { version = "0.3", default-features = false, features = ["t
|
||||
vodozemac = { workspace = true, features = ["js"] }
|
||||
zeroize = { workspace = true }
|
||||
|
||||
[dependencies.matrix-sdk-crypto]
|
||||
path = "../../crates/matrix-sdk-crypto"
|
||||
version = "0.6.0"
|
||||
default_features = false
|
||||
features = ["js", "automatic-room-key-forwarding"]
|
||||
|
||||
[build-dependencies]
|
||||
napi-build = "2.0.0"
|
||||
|
||||
@@ -21,6 +21,7 @@ e2e-encryption = ["dep:matrix-sdk-crypto"]
|
||||
js = ["matrix-sdk-common/js", "matrix-sdk-crypto?/js", "ruma/js", "matrix-sdk-store-encryption/js"]
|
||||
qrcode = ["matrix-sdk-crypto?/qrcode"]
|
||||
automatic-room-key-forwarding = ["matrix-sdk-crypto?/automatic-room-key-forwarding"]
|
||||
message-ids = ["matrix-sdk-crypto?/message-ids"]
|
||||
experimental-sliding-sync = ["ruma/unstable-msc3575"]
|
||||
|
||||
# helpers for testing features build upon this
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# v0.7.0
|
||||
|
||||
- Add a new optional `message-ids` feature which adds a unique ID to the content
|
||||
of `m.room.encrypted` event contents which get sent out.
|
||||
|
||||
- Disable the automatic-key-forwarding feature by default.
|
||||
|
||||
- Add a new variant to the `VerificationRequestState` enum called
|
||||
|
||||
@@ -20,6 +20,7 @@ automatic-room-key-forwarding = []
|
||||
js = ["ruma/js", "vodozemac/js"]
|
||||
qrcode = ["dep:matrix-sdk-qrcode"]
|
||||
backups_v1 = ["dep:bs58", "dep:cbc", "dep:hkdf"]
|
||||
message-ids = ["dep:ulid"]
|
||||
experimental-algorithms = []
|
||||
|
||||
# Testing helpers for implementations based upon this
|
||||
@@ -48,15 +49,16 @@ matrix-sdk-qrcode = { version = "0.4.0", path = "../matrix-sdk-qrcode", optional
|
||||
matrix-sdk-common = { version = "0.6.0", path = "../matrix-sdk-common" }
|
||||
pbkdf2 = { version = "0.11.0", default-features = false }
|
||||
rand = "0.8.5"
|
||||
rmp-serde = "1.1.1"
|
||||
ruma = { workspace = true, features = ["rand", "canonical-json", "unstable-msc2677"] }
|
||||
serde = { workspace = true, features = ["derive", "rc"] }
|
||||
rmp-serde = "1.1.1"
|
||||
serde_json = { workspace = true }
|
||||
sha2 = "0.10.2"
|
||||
tokio-stream = { version = "0.1.12", features = ["sync"] }
|
||||
tokio = { workspace = true, default-features = false, features = ["sync"] }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true, features = ["attributes"] }
|
||||
ulid = { version = "1.0.0", optional = true }
|
||||
vodozemac = { workspace = true }
|
||||
zeroize = { workspace = true, features = ["zeroize_derive"] }
|
||||
|
||||
|
||||
@@ -440,6 +440,7 @@ impl Device {
|
||||
recipient_key = ?self.curve25519_key(),
|
||||
event_type,
|
||||
session,
|
||||
message_id,
|
||||
))
|
||||
]
|
||||
pub(crate) async fn encrypt(
|
||||
@@ -447,7 +448,23 @@ impl Device {
|
||||
event_type: &str,
|
||||
content: Value,
|
||||
) -> OlmResult<(Session, Raw<ToDeviceEncryptedEventContent>)> {
|
||||
self.inner.encrypt(self.verification_machine.store.inner(), event_type, content).await
|
||||
#[cfg(feature = "message-ids")]
|
||||
let message_id = {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let id = ulid::Ulid::new().to_string();
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let id = ruma::TransactionId::new().to_string();
|
||||
|
||||
tracing::Span::current().record("message_id", &id);
|
||||
Some(id)
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "message-ids"))]
|
||||
let message_id = None;
|
||||
|
||||
self.inner
|
||||
.encrypt(self.verification_machine.store.inner(), event_type, content, message_id)
|
||||
.await
|
||||
}
|
||||
|
||||
pub(crate) async fn maybe_encrypt_room_key(
|
||||
@@ -779,11 +796,12 @@ impl ReadOnlyDevice {
|
||||
store: &DynCryptoStore,
|
||||
event_type: &str,
|
||||
content: Value,
|
||||
message_id: Option<String>,
|
||||
) -> OlmResult<(Session, Raw<ToDeviceEncryptedEventContent>)> {
|
||||
let session = self.get_most_recent_session(store).await?;
|
||||
|
||||
if let Some(mut session) = session {
|
||||
let message = session.encrypt(self, event_type, content).await?;
|
||||
let message = session.encrypt(self, event_type, content, message_id).await?;
|
||||
|
||||
trace!("Successfully encrypted an event");
|
||||
|
||||
|
||||
@@ -1204,6 +1204,7 @@ impl ReadOnlyAccount {
|
||||
&device,
|
||||
"m.dummy",
|
||||
serde_json::to_value(ToDeviceDummyEventContent::new()).unwrap(),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
use std::{fmt, sync::Arc};
|
||||
|
||||
use ruma::{serde::Raw, OwnedDeviceId, OwnedUserId, SecondsSinceUnixEpoch};
|
||||
use ruma::{serde::Raw, JsOption, OwnedDeviceId, OwnedUserId, SecondsSinceUnixEpoch};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use tokio::sync::Mutex;
|
||||
@@ -151,6 +151,7 @@ impl Session {
|
||||
recipient_device: &ReadOnlyDevice,
|
||||
event_type: &str,
|
||||
content: Value,
|
||||
message_id: Option<String>,
|
||||
) -> OlmResult<Raw<ToDeviceEncryptedEventContent>> {
|
||||
let plaintext = {
|
||||
let recipient_signing_key =
|
||||
@@ -180,12 +181,14 @@ impl Session {
|
||||
ciphertext,
|
||||
recipient_key: self.sender_key,
|
||||
sender_key: self.our_identity_keys.curve25519,
|
||||
message_id: JsOption::from_implicit_option(message_id),
|
||||
}
|
||||
.into(),
|
||||
#[cfg(feature = "experimental-algorithms")]
|
||||
EventEncryptionAlgorithm::OlmV2Curve25519AesSha2 => OlmV2Curve25519AesSha2Content {
|
||||
ciphertext,
|
||||
sender_key: self.our_identity_keys.curve25519,
|
||||
message_id: JsOption::from_implicit_option(message_id),
|
||||
}
|
||||
.into(),
|
||||
_ => unreachable!(),
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use ruma::{OwnedDeviceId, RoomId};
|
||||
use ruma::{JsOption, OwnedDeviceId, RoomId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use vodozemac::{megolm::MegolmMessage, olm::OlmMessage, Curve25519PublicKey};
|
||||
@@ -124,6 +124,9 @@ pub struct OlmV1Curve25519AesSha2Content {
|
||||
|
||||
/// The Curve25519 key of the sender.
|
||||
pub sender_key: Curve25519PublicKey,
|
||||
|
||||
/// The unique ID of this content.
|
||||
pub message_id: JsOption<String>,
|
||||
}
|
||||
|
||||
/// The event content for events encrypted with the m.olm.v2.curve25519-aes-sha2
|
||||
@@ -137,6 +140,10 @@ pub struct OlmV2Curve25519AesSha2Content {
|
||||
/// The Curve25519 key of the sender.
|
||||
#[serde(deserialize_with = "deserialize_curve_key", serialize_with = "serialize_curve_key")]
|
||||
pub sender_key: Curve25519PublicKey,
|
||||
|
||||
/// The unique ID of this content.
|
||||
#[serde(default, skip_serializing_if = "JsOption::is_undefined", rename = "org.matrix.msgid")]
|
||||
pub message_id: JsOption<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||
@@ -144,6 +151,8 @@ struct OlmHelper {
|
||||
#[serde(deserialize_with = "deserialize_curve_key", serialize_with = "serialize_curve_key")]
|
||||
sender_key: Curve25519PublicKey,
|
||||
ciphertext: BTreeMap<String, OlmMessage>,
|
||||
#[serde(default, skip_serializing_if = "JsOption::is_undefined", rename = "org.matrix.msgid")]
|
||||
message_id: JsOption<String>,
|
||||
}
|
||||
|
||||
impl Serialize for OlmV1Curve25519AesSha2Content {
|
||||
@@ -154,7 +163,12 @@ impl Serialize for OlmV1Curve25519AesSha2Content {
|
||||
let ciphertext =
|
||||
BTreeMap::from([(self.recipient_key.to_base64(), self.ciphertext.clone())]);
|
||||
|
||||
OlmHelper { sender_key: self.sender_key, ciphertext }.serialize(serializer)
|
||||
OlmHelper {
|
||||
sender_key: self.sender_key,
|
||||
ciphertext,
|
||||
message_id: self.message_id.to_owned(),
|
||||
}
|
||||
.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +185,12 @@ impl TryFrom<OlmHelper> for OlmV1Curve25519AesSha2Content {
|
||||
let recipient_key =
|
||||
Curve25519PublicKey::from_base64(&recipient_key).map_err(serde::de::Error::custom)?;
|
||||
|
||||
Ok(Self { ciphertext, recipient_key, sender_key: value.sender_key })
|
||||
Ok(Self {
|
||||
ciphertext,
|
||||
recipient_key,
|
||||
sender_key: value.sender_key,
|
||||
message_id: value.message_id,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,7 +498,11 @@ pub(crate) mod test {
|
||||
let json = to_device_json();
|
||||
let event: EncryptedToDeviceEvent = serde_json::from_value(json.clone())?;
|
||||
|
||||
assert_matches!(event.content, ToDeviceEncryptedEventContent::OlmV1Curve25519AesSha2(_));
|
||||
let content = assert_matches!(
|
||||
&event.content,
|
||||
ToDeviceEncryptedEventContent::OlmV1Curve25519AesSha2(c) => c.to_owned()
|
||||
);
|
||||
assert!(content.message_id.is_undefined());
|
||||
|
||||
let serialized = serde_json::to_value(event)?;
|
||||
assert_eq!(json, serialized);
|
||||
|
||||
@@ -26,6 +26,7 @@ testing = []
|
||||
|
||||
e2e-encryption = [
|
||||
"matrix-sdk-base/e2e-encryption",
|
||||
"matrix-sdk-base/message-ids",
|
||||
"matrix-sdk-sqlite?/crypto-store", # activate crypto-store on sqlite if given
|
||||
"matrix-sdk-indexeddb?/e2e-encryption", # activate on indexeddb if given
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user