matrix_sdk_crypto/types/events/
forwarded_room_key.rs1use std::collections::BTreeMap;
18
19use ruma::{DeviceKeyAlgorithm, OwnedRoomId};
20use serde::{Deserialize, Serialize};
21use serde_json::Value;
22use vodozemac::{Curve25519PublicKey, Ed25519PublicKey, megolm::ExportedSessionKey};
23
24use super::{EventType, ToDeviceEvent};
25#[cfg(doc)]
26use crate::olm::InboundGroupSession;
27use crate::types::{
28 EventEncryptionAlgorithm, SigningKeys, deserialize_curve_key, deserialize_curve_key_vec,
29 deserialize_ed25519_key, serialize_curve_key, serialize_curve_key_vec, serialize_ed25519_key,
30};
31
32pub type ForwardedRoomKeyEvent = ToDeviceEvent<ForwardedRoomKeyContent>;
34
35impl ForwardedRoomKeyEvent {
36 pub fn algorithm(&self) -> EventEncryptionAlgorithm {
38 self.content.algorithm()
39 }
40}
41
42#[derive(Debug, Deserialize)]
54#[serde(try_from = "RoomKeyHelper")]
55pub enum ForwardedRoomKeyContent {
56 MegolmV1AesSha2(Box<ForwardedMegolmV1AesSha2Content>),
59 #[cfg(feature = "experimental-algorithms")]
62 MegolmV2AesSha2(Box<ForwardedMegolmV2AesSha2Content>),
63 Unknown(UnknownRoomKeyContent),
66}
67
68impl ForwardedRoomKeyContent {
69 pub fn algorithm(&self) -> EventEncryptionAlgorithm {
71 match self {
72 ForwardedRoomKeyContent::MegolmV1AesSha2(_) => {
73 EventEncryptionAlgorithm::MegolmV1AesSha2
74 }
75 #[cfg(feature = "experimental-algorithms")]
76 ForwardedRoomKeyContent::MegolmV2AesSha2(_) => {
77 EventEncryptionAlgorithm::MegolmV2AesSha2
78 }
79 ForwardedRoomKeyContent::Unknown(c) => c.algorithm.to_owned(),
80 }
81 }
82}
83
84impl EventType for ForwardedRoomKeyContent {
85 const EVENT_TYPE: &'static str = "m.forwarded_room_key";
86}
87
88#[derive(Deserialize, Serialize)]
90pub struct ForwardedMegolmV1AesSha2Content {
91 pub room_id: OwnedRoomId,
93
94 pub session_id: String,
96
97 pub session_key: ExportedSessionKey,
102
103 #[serde(
107 deserialize_with = "deserialize_curve_key_vec",
108 serialize_with = "serialize_curve_key_vec"
109 )]
110 pub forwarding_curve25519_key_chain: Vec<Curve25519PublicKey>,
111
112 #[serde(
118 rename = "sender_key",
119 deserialize_with = "deserialize_curve_key",
120 serialize_with = "serialize_curve_key"
121 )]
122 pub claimed_sender_key: Curve25519PublicKey,
123
124 #[serde(
130 rename = "sender_claimed_ed25519_key",
131 deserialize_with = "deserialize_ed25519_key",
132 serialize_with = "serialize_ed25519_key"
133 )]
134 pub claimed_ed25519_key: Ed25519PublicKey,
135
136 #[serde(flatten)]
137 pub(crate) other: BTreeMap<String, Value>,
138}
139
140#[derive(Deserialize, Serialize)]
142pub struct ForwardedMegolmV2AesSha2Content {
143 pub room_id: OwnedRoomId,
145
146 pub session_id: String,
148
149 pub session_key: ExportedSessionKey,
154
155 #[serde(deserialize_with = "deserialize_curve_key", serialize_with = "serialize_curve_key")]
161 pub claimed_sender_key: Curve25519PublicKey,
162
163 #[serde(default)]
169 pub claimed_signing_keys: SigningKeys<DeviceKeyAlgorithm>,
170
171 #[serde(flatten)]
172 pub(crate) other: BTreeMap<String, Value>,
173}
174
175#[derive(Clone, Debug, Serialize, Deserialize)]
177pub struct UnknownRoomKeyContent {
178 pub algorithm: EventEncryptionAlgorithm,
180 #[serde(flatten)]
182 other: BTreeMap<String, Value>,
183}
184
185#[cfg(not(tarpaulin_include))]
186impl std::fmt::Debug for ForwardedMegolmV1AesSha2Content {
187 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188 f.debug_struct("ForwardedMegolmV1AesSha2Content")
189 .field("room_id", &self.room_id)
190 .field("session_id", &self.session_id)
191 .field("forwarding_curve25519_key_chain", &self.forwarding_curve25519_key_chain)
192 .field("claimed_sender_key", &self.claimed_sender_key)
193 .field("claimed_ed25519_key", &self.claimed_ed25519_key)
194 .finish_non_exhaustive()
195 }
196}
197
198#[cfg(not(tarpaulin_include))]
199impl std::fmt::Debug for ForwardedMegolmV2AesSha2Content {
200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201 f.debug_struct("ForwardedMegolmV2AesSha2Content")
202 .field("room_id", &self.room_id)
203 .field("session_id", &self.session_id)
204 .field("claimed_sender_key", &self.claimed_sender_key)
205 .field("sender_claimed_keys", &self.claimed_signing_keys)
206 .finish_non_exhaustive()
207 }
208}
209
210#[derive(Deserialize, Serialize)]
211struct RoomKeyHelper {
212 algorithm: EventEncryptionAlgorithm,
213 #[serde(flatten)]
214 other: Value,
215}
216
217impl TryFrom<RoomKeyHelper> for ForwardedRoomKeyContent {
218 type Error = serde_json::Error;
219
220 fn try_from(value: RoomKeyHelper) -> Result<Self, Self::Error> {
221 Ok(match value.algorithm {
222 EventEncryptionAlgorithm::MegolmV1AesSha2 => {
223 let content: ForwardedMegolmV1AesSha2Content = serde_json::from_value(value.other)?;
224 Self::MegolmV1AesSha2(content.into())
225 }
226 #[cfg(feature = "experimental-algorithms")]
227 EventEncryptionAlgorithm::MegolmV2AesSha2 => {
228 let content: ForwardedMegolmV2AesSha2Content = serde_json::from_value(value.other)?;
229 Self::MegolmV2AesSha2(content.into())
230 }
231 _ => Self::Unknown(UnknownRoomKeyContent {
232 algorithm: value.algorithm,
233 other: serde_json::from_value(value.other)?,
234 }),
235 })
236 }
237}
238
239impl Serialize for ForwardedRoomKeyContent {
240 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
241 where
242 S: serde::Serializer,
243 {
244 let helper = match self {
245 Self::MegolmV1AesSha2(r) => RoomKeyHelper {
246 algorithm: EventEncryptionAlgorithm::MegolmV1AesSha2,
247 other: serde_json::to_value(r).map_err(serde::ser::Error::custom)?,
248 },
249 #[cfg(feature = "experimental-algorithms")]
250 Self::MegolmV2AesSha2(r) => RoomKeyHelper {
251 algorithm: EventEncryptionAlgorithm::MegolmV2AesSha2,
252 other: serde_json::to_value(r).map_err(serde::ser::Error::custom)?,
253 },
254 Self::Unknown(r) => RoomKeyHelper {
255 algorithm: r.algorithm.clone(),
256 other: serde_json::to_value(r.other.clone()).map_err(serde::ser::Error::custom)?,
257 },
258 };
259
260 helper.serialize(serializer)
261 }
262}