core_crypto/mls/conversation/conversation_guard/
encrypt.rs1use super::ConversationGuard;
4use super::Result;
5use crate::MlsError;
6use crate::mls::conversation::ConversationWithMls as _;
7use openmls::prelude::MlsMessageOutBody;
8
9impl ConversationGuard {
10 pub async fn encrypt_message(&mut self, message: impl AsRef<[u8]>) -> Result<Vec<u8>> {
23 let backend = self.crypto_provider().await?;
24 let credential = self.credential_bundle().await?;
25 let signer = credential.signature_key();
26 let mut inner = self.conversation_mut().await;
27 let encrypted = inner
28 .group
29 .create_message(&backend, signer, message.as_ref())
30 .map_err(MlsError::wrap("creating message"))?;
31
32 debug_assert!(matches!(encrypted.body, MlsMessageOutBody::PrivateMessage(_)));
34
35 let encrypted = encrypted
36 .to_bytes()
37 .map_err(MlsError::wrap("constructing byte vector of encrypted message"))?;
38
39 inner.persist_group_when_changed(&backend.keystore(), false).await?;
40 Ok(encrypted)
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use wasm_bindgen_test::*;
47
48 use crate::test_utils::*;
49
50 wasm_bindgen_test_configure!(run_in_browser);
51
52 #[apply(all_cred_cipher)]
53 #[wasm_bindgen_test]
54 async fn can_encrypt_app_message(case: TestContext) {
55 let [alice_central, bob_central] = case.sessions().await;
56 Box::pin(async move {
57 let id = conversation_id();
58 alice_central
59 .transaction
60 .new_conversation(&id, case.credential_type, case.cfg.clone())
61 .await
62 .unwrap();
63 alice_central.invite_all(&case, &id, [&bob_central]).await.unwrap();
64
65 let msg = b"Hello bob";
66 let encrypted = alice_central
67 .transaction
68 .conversation(&id)
69 .await
70 .unwrap()
71 .encrypt_message(msg)
72 .await
73 .unwrap();
74 assert_ne!(&msg[..], &encrypted[..]);
75 let decrypted = bob_central
76 .transaction
77 .conversation(&id)
78 .await
79 .unwrap()
80 .decrypt_message(encrypted)
81 .await
82 .unwrap()
83 .app_msg
84 .unwrap();
85 assert_eq!(&decrypted[..], &msg[..]);
86 })
87 .await
88 }
89
90 #[apply(all_cred_cipher)]
92 #[wasm_bindgen_test]
93 async fn can_encrypt_consecutive_messages(case: TestContext) {
94 let [alice_central, bob_central] = case.sessions().await;
95 Box::pin(async move {
96 let id = conversation_id();
97 alice_central
98 .transaction
99 .new_conversation(&id, case.credential_type, case.cfg.clone())
100 .await
101 .unwrap();
102 alice_central.invite_all(&case, &id, [&bob_central]).await.unwrap();
103 let mut alice_conversation = alice_central.transaction.conversation(&id).await.unwrap();
104
105 let msg = b"Hello bob";
106 let encrypted = alice_conversation.encrypt_message(msg).await.unwrap();
107 assert_ne!(&msg[..], &encrypted[..]);
108 let decrypted = bob_central
109 .transaction
110 .conversation(&id)
111 .await
112 .unwrap()
113 .decrypt_message(encrypted)
114 .await
115 .unwrap()
116 .app_msg
117 .unwrap();
118 assert_eq!(&decrypted[..], &msg[..]);
119
120 let msg = b"Hello bob again";
121 let encrypted = alice_conversation.encrypt_message(msg).await.unwrap();
122 assert_ne!(&msg[..], &encrypted[..]);
123 let decrypted = bob_central
124 .transaction
125 .conversation(&id)
126 .await
127 .unwrap()
128 .decrypt_message(encrypted)
129 .await
130 .unwrap()
131 .app_msg
132 .unwrap();
133 assert_eq!(&decrypted[..], &msg[..]);
134 })
135 .await
136 }
137}