core_crypto/mls/conversation/
encrypt.rsuse mls_crypto_provider::MlsCryptoProvider;
use openmls::prelude::MlsMessageOutBody;
use super::MlsConversation;
use crate::context::CentralContext;
use crate::prelude::Client;
use crate::{mls::ConversationId, CryptoError, CryptoResult, MlsError};
impl MlsConversation {
#[cfg_attr(test, crate::durable)]
pub async fn encrypt_message(
&mut self,
client: &Client,
message: impl AsRef<[u8]>,
backend: &MlsCryptoProvider,
) -> CryptoResult<Vec<u8>> {
let signer = &self
.find_current_credential_bundle(client)
.await
.map_err(|_| CryptoError::IdentityInitializationError)?
.signature_key;
let encrypted = self
.group
.create_message(backend, signer, message.as_ref())
.map_err(MlsError::from)?;
debug_assert!(matches!(encrypted.body, MlsMessageOutBody::PrivateMessage(_)));
let encrypted = encrypted.to_bytes().map_err(MlsError::from)?;
self.persist_group_when_changed(&backend.keystore(), false).await?;
Ok(encrypted)
}
}
impl CentralContext {
#[cfg_attr(test, crate::idempotent)]
pub async fn encrypt_message(
&self,
conversation: &ConversationId,
message: impl AsRef<[u8]>,
) -> CryptoResult<Vec<u8>> {
let client = self.mls_client().await?;
self.get_conversation(conversation)
.await?
.write()
.await
.encrypt_message(&client, message, &self.mls_provider().await?)
.await
}
}
#[cfg(test)]
mod tests {
use wasm_bindgen_test::*;
use crate::test_utils::*;
wasm_bindgen_test_configure!(run_in_browser);
#[apply(all_cred_cipher)]
#[wasm_bindgen_test]
async fn can_encrypt_app_message(case: TestCase) {
run_test_with_client_ids(case.clone(), ["alice", "bob"], move |[alice_central, bob_central]| {
Box::pin(async move {
let id = conversation_id();
alice_central
.context
.new_conversation(&id, case.credential_type, case.cfg.clone())
.await
.unwrap();
alice_central.invite_all(&case, &id, [&bob_central]).await.unwrap();
let msg = b"Hello bob";
let encrypted = alice_central.context.encrypt_message(&id, msg).await.unwrap();
assert_ne!(&msg[..], &encrypted[..]);
let decrypted = bob_central
.context
.decrypt_message(&id, encrypted)
.await
.unwrap()
.app_msg
.unwrap();
assert_eq!(&decrypted[..], &msg[..]);
})
})
.await
}
#[apply(all_cred_cipher)]
#[wasm_bindgen_test]
async fn can_encrypt_consecutive_messages(case: TestCase) {
run_test_with_client_ids(case.clone(), ["alice", "bob"], move |[alice_central, bob_central]| {
Box::pin(async move {
let id = conversation_id();
alice_central
.context
.new_conversation(&id, case.credential_type, case.cfg.clone())
.await
.unwrap();
alice_central.invite_all(&case, &id, [&bob_central]).await.unwrap();
let msg = b"Hello bob";
let encrypted = alice_central.context.encrypt_message(&id, msg).await.unwrap();
assert_ne!(&msg[..], &encrypted[..]);
let decrypted = bob_central
.context
.decrypt_message(&id, encrypted)
.await
.unwrap()
.app_msg
.unwrap();
assert_eq!(&decrypted[..], &msg[..]);
let msg = b"Hello bob again";
let encrypted = alice_central.context.encrypt_message(&id, msg).await.unwrap();
assert_ne!(&msg[..], &encrypted[..]);
let decrypted = bob_central
.context
.decrypt_message(&id, encrypted)
.await
.unwrap()
.app_msg
.unwrap();
assert_eq!(&decrypted[..], &msg[..]);
})
})
.await
}
}