//! Task for sending an outgoing message.
use libthreema_dependencies::crypto::aead::AeadInPlace as _;
use crate::{
common::{MessageMetadata, Nonce, ThreemaId, keys::CspE2eKey},
csp_e2e::message::{
MessageProperties, OutgoingMessage, codec::CspMessageEncoder as _,
payload::OutgoingMessageWithMetadataBox,
},
utils::bytes::OwnedVecByteWriter,
};
pub(super) fn encode_metadata(
sender_nickname: Option<&str>,
message: &OutgoingMessage,
effective_message_properties: &MessageProperties,
) -> Vec<u8> {
MessageMetadata {
message_id: message.message_id,
created_at: message.created_at,
nickname: if effective_message_properties.user_profile_distribution {
sender_nickname.map(ToOwned::to_owned)
} else {
None
},
}
.into()
}
// TODO(LIB-51): Make encryption fallible
pub(super) fn encrypt_metadata_in_place(shared_secret: &CspE2eKey, nonce: &Nonce, metadata: &n style='color:red'>mut Vec<u8>) {
shared_secret
.message_metadata_cipher()
.0
.encrypt_in_place(&nonce.0.into(), b"", metadata)
.expect("metadata encryption should not fail");
}
// TODO(LIB-51): Make encryption fallible
pub(super) fn encrypt_message_container_in_place(
shared_secret: &CspE2eKey,
nonce: &Nonce,
message_container: &mut Vec<u8>,
) {
shared_secret
.message_cipher()
.0
.encrypt_in_place(&nonce.0.into(), b"", message_container)
.expect("message container encryption should not fail");
}
#[expect(unused, reason = "TODO(LIB-51)")]
pub(super) fn encode_and_encrypt_message(
sender_identity: ThreemaId,
(legacy_sender_nickname, sender_nickname): (&str, Option<&str>),
receiver_identity: ThreemaId,
shared_secret: CspE2eKey,
message: &OutgoingMessage,
nonce: Nonce,
) -> OutgoingMessageWithMetadataBox {
let effective_message_properties = message.effective_properties();
// Encode and encrypt metadata
let metadata = {
let mut metadata = encode_metadata(sender_nickname, message, &effective_message_properties);
encrypt_metadata_in_place(&shared_secret, &nonce, &mut metadata);
metadata
};
// Encode and encrypt message container
let message_container = {
// Note: The effort to calculate the required capacity for all message types would be unreasonable, so
// we don't.
let mut writer = OwnedVecByteWriter::new_empty();
// Encode message container (i.e. message type, data and PKCS#7 padding)
message
.body
.encode_into(&mut writer)
.expect("encoding message container with OwnedVecByteWriter should not fail");
let mut message_container = writer.into_inner();
// Encrypt message container
encrypt_message_container_in_place(&shared_secret, &nonce, &mut message_container);
message_container
};
// Drop shared secret ASAP
drop(shared_secret);
// Encode legacy created-at timestamp
let legacy_created_at: u32 = message
.created_at
.checked_div_euclid(1000)
.expect("ms to s conversion should work")
.try_into()
.unwrap_or(u32::MAX);
// Encode legacy sender nickname (if applicable and towards a Gateway ID)
let legacy_sender_nickname =
if effective_message_properties.user_profile_distribution && receiver_identity.is_gateway_id() {
legacy_sender_nickname.to_owned()
} else {
String::default()
};
// Done
OutgoingMessageWithMetadataBox {
sender_identity,
receiver_identity,
message_id: message.message_id,
legacy_created_at,
flags: message.flags(),
legacy_sender_nickname,
metadata,
nonce,
message_container,
}
}
¤ Dauer der Verarbeitung: 0.4 Sekunden
¤
*© Formatika GbR, Deutschland
|
|