Skip to content

Commit 924fea6

Browse files
committed
feat(crypto): Add OutboundGroupSession::encrypt_state
This commit also refactors out what would be common code between ::encrypt and ::encrypt_state to a helper ::encrypt_inner. Signed-off-by: Skye Elliot <[email protected]>
1 parent eefa9ff commit 924fea6

File tree

1 file changed

+84
-22
lines changed
  • crates/matrix-sdk-crypto/src/olm/group_sessions

1 file changed

+84
-22
lines changed

crates/matrix-sdk-crypto/src/olm/group_sessions/outbound.rs

Lines changed: 84 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ use std::{
2525
};
2626

2727
use matrix_sdk_common::{deserialized_responses::WithheldCode, locks::RwLock as StdRwLock};
28+
#[cfg(feature = "experimental-encrypted-state-events")]
29+
use ruma::events::AnyStateEventContent;
2830
use ruma::{
2931
events::{
3032
room::{encryption::RoomEncryptionEventContent, history_visibility::HistoryVisibility},
@@ -458,6 +460,50 @@ impl OutboundGroupSession {
458460
session.encrypt(&plaintext)
459461
}
460462

463+
/// Encrypt an arbitrary event for the given room.
464+
///
465+
/// Beware that a room key needs to be shared before this method
466+
/// can be called using the `share_room_key()` method.
467+
///
468+
/// # Arguments
469+
///
470+
/// * `payload` - The plaintext content of the event that should be
471+
/// encrypted in raw JSON form.
472+
///
473+
/// # Panics
474+
///
475+
/// Panics if the content can't be serialized.
476+
async fn encrypt_inner<T: Serialize>(
477+
&self,
478+
payload: &T,
479+
relates_to: Option<serde_json::Value>,
480+
) -> Raw<RoomEncryptedEventContent> {
481+
let ciphertext = self
482+
.encrypt_helper(
483+
serde_json::to_string(payload).expect("payload serialization never fails"),
484+
)
485+
.await;
486+
let scheme: RoomEventEncryptionScheme = match self.settings.algorithm {
487+
EventEncryptionAlgorithm::MegolmV1AesSha2 => MegolmV1AesSha2Content {
488+
ciphertext,
489+
sender_key: Some(self.account_identity_keys.curve25519),
490+
session_id: self.session_id().to_owned(),
491+
device_id: Some(self.device_id.clone()),
492+
}
493+
.into(),
494+
#[cfg(feature = "experimental-algorithms")]
495+
EventEncryptionAlgorithm::MegolmV2AesSha2 => {
496+
MegolmV2AesSha2Content { ciphertext, session_id: self.session_id().to_owned() }
497+
.into()
498+
}
499+
_ => unreachable!(
500+
"An outbound group session is always using one of the supported algorithms"
501+
),
502+
};
503+
let content = RoomEncryptedEventContent { scheme, relates_to, other: Default::default() };
504+
Raw::new(&content).expect("m.room.encrypted event content can always be serialized")
505+
}
506+
461507
/// Encrypt a room message for the given room.
462508
///
463509
/// Beware that a room key needs to be shared before this method
@@ -488,35 +534,51 @@ impl OutboundGroupSession {
488534
}
489535

490536
let payload = Payload { event_type, content, room_id: &self.room_id };
491-
let payload_json =
492-
serde_json::to_string(&payload).expect("payload serialization never fails");
493537

494538
let relates_to = content
495539
.get_field::<serde_json::Value>("m.relates_to")
496540
.expect("serde_json::Value deserialization with valid JSON input never fails");
497541

498-
let ciphertext = self.encrypt_helper(payload_json).await;
499-
let scheme: RoomEventEncryptionScheme = match self.settings.algorithm {
500-
EventEncryptionAlgorithm::MegolmV1AesSha2 => MegolmV1AesSha2Content {
501-
ciphertext,
502-
sender_key: Some(self.account_identity_keys.curve25519),
503-
session_id: self.session_id().to_owned(),
504-
device_id: Some(self.device_id.clone()),
505-
}
506-
.into(),
507-
#[cfg(feature = "experimental-algorithms")]
508-
EventEncryptionAlgorithm::MegolmV2AesSha2 => {
509-
MegolmV2AesSha2Content { ciphertext, session_id: self.session_id().to_owned() }
510-
.into()
511-
}
512-
_ => unreachable!(
513-
"An outbound group session is always using one of the supported algorithms"
514-
),
515-
};
542+
self.encrypt_inner(&payload, relates_to).await
543+
}
516544

517-
let content = RoomEncryptedEventContent { scheme, relates_to, other: Default::default() };
545+
/// Encrypt a room state event for the given room.
546+
///
547+
/// Beware that a room key needs to be shared before this method
548+
/// can be called using the `share_room_key()` method.
549+
///
550+
/// # Arguments
551+
///
552+
/// * `event_type` - The plaintext type of the event, the outer type of the
553+
/// event will become `m.room.encrypted`.
554+
///
555+
/// * `state_key` - The plaintext state key of the event, the outer state
556+
/// key will be derived from this and the event type.
557+
///
558+
/// * `content` - The plaintext content of the message that should be
559+
/// encrypted in raw JSON form.
560+
///
561+
/// # Panics
562+
///
563+
/// Panics if the content can't be serialized.
564+
#[cfg(feature = "experimental-encrypted-state-events")]
565+
pub async fn encrypt_state(
566+
&self,
567+
event_type: &str,
568+
state_key: &str,
569+
content: &Raw<AnyStateEventContent>,
570+
) -> Raw<RoomEncryptedEventContent> {
571+
#[derive(Serialize)]
572+
struct Payload<'a> {
573+
#[serde(rename = "type")]
574+
event_type: &'a str,
575+
state_key: &'a str,
576+
content: &'a Raw<AnyStateEventContent>,
577+
room_id: &'a RoomId,
578+
}
518579

519-
Raw::new(&content).expect("m.room.encrypted event content can always be serialized")
580+
let payload = Payload { event_type, state_key, content, room_id: &self.room_id };
581+
self.encrypt_inner(&payload, None).await.cast_unchecked()
520582
}
521583

522584
fn elapsed(&self) -> bool {

0 commit comments

Comments
 (0)