mirror of
https://github.com/chatmail/core.git
synced 2026-05-07 08:56:30 +03:00
WIP, untested: Sending side of transferring the secret in member-added message
This commit is contained in:
14
src/chat.rs
14
src/chat.rs
@@ -42,9 +42,9 @@ use crate::smtp::send_msg_to_smtp;
|
|||||||
use crate::stock_str;
|
use crate::stock_str;
|
||||||
use crate::sync::{self, Sync::*, SyncData};
|
use crate::sync::{self, Sync::*, SyncData};
|
||||||
use crate::tools::{
|
use crate::tools::{
|
||||||
IsNoneOrEmpty, SystemTime, buf_compress, create_id, create_outgoing_rfc724_mid,
|
IsNoneOrEmpty, SystemTime, buf_compress, create_broadcast_shared_secret, create_id,
|
||||||
create_smeared_timestamp, create_smeared_timestamps, get_abs_path, gm2local_offset,
|
create_outgoing_rfc724_mid, create_smeared_timestamp, create_smeared_timestamps, get_abs_path,
|
||||||
smeared_time, time, truncate_msg_text,
|
gm2local_offset, smeared_time, time, truncate_msg_text,
|
||||||
};
|
};
|
||||||
use crate::webxdc::StatusUpdateSerial;
|
use crate::webxdc::StatusUpdateSerial;
|
||||||
use crate::{chatlist_events, imap};
|
use crate::{chatlist_events, imap};
|
||||||
@@ -3710,14 +3710,18 @@ pub(crate) async fn create_broadcast_ex(
|
|||||||
},
|
},
|
||||||
)?);
|
)?);
|
||||||
}
|
}
|
||||||
|
let mut param = Params::new();
|
||||||
|
// param.set(Param::Unpromoted, 1); // TODO broadcasts will just never be unpromoted for now
|
||||||
|
param.set(Param::SymmetricKey, create_broadcast_shared_secret());
|
||||||
t.execute(
|
t.execute(
|
||||||
"INSERT INTO chats \
|
"INSERT INTO chats \
|
||||||
(type, name, grpid, param, created_timestamp) \
|
(type, name, grpid, param, created_timestamp) \
|
||||||
VALUES(?, ?, ?, \'U=1\', ?);",
|
VALUES(?, ?, ?, ?, ?);",
|
||||||
(
|
(
|
||||||
Chattype::OutBroadcast,
|
Chattype::OutBroadcast,
|
||||||
&chat_name,
|
&chat_name,
|
||||||
&grpid,
|
&grpid,
|
||||||
|
param.to_string(),
|
||||||
create_smeared_timestamp(context),
|
create_smeared_timestamp(context),
|
||||||
),
|
),
|
||||||
)?;
|
)?;
|
||||||
@@ -3918,7 +3922,7 @@ pub(crate) async fn add_contact_to_chat_ex(
|
|||||||
}
|
}
|
||||||
add_to_chat_contacts_table(context, time(), chat_id, &[contact_id]).await?;
|
add_to_chat_contacts_table(context, time(), chat_id, &[contact_id]).await?;
|
||||||
}
|
}
|
||||||
if chat.typ == Chattype::Group && chat.is_promoted() {
|
if chat.is_promoted() {
|
||||||
msg.viewtype = Viewtype::Text;
|
msg.viewtype = Viewtype::Text;
|
||||||
|
|
||||||
let contact_addr = contact.get_addr().to_lowercase();
|
let contact_addr = contact.get_addr().to_lowercase();
|
||||||
|
|||||||
@@ -93,6 +93,10 @@ pub enum HeaderDef {
|
|||||||
/// This message obsoletes the text of the message defined here by rfc724_mid.
|
/// This message obsoletes the text of the message defined here by rfc724_mid.
|
||||||
ChatEdit,
|
ChatEdit,
|
||||||
|
|
||||||
|
/// The secret shared amongst all recipients of this broadcast channel.
|
||||||
|
/// This secret.
|
||||||
|
ChatBroadcastSecret,
|
||||||
|
|
||||||
/// [Autocrypt](https://autocrypt.org/) header.
|
/// [Autocrypt](https://autocrypt.org/) header.
|
||||||
Autocrypt,
|
Autocrypt,
|
||||||
AutocryptGossip,
|
AutocryptGossip,
|
||||||
|
|||||||
@@ -789,7 +789,7 @@ impl MimeFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Loaded::Message { chat, .. } = &self.loaded {
|
if let Loaded::Message { msg, chat } = &self.loaded {
|
||||||
if chat.typ == Chattype::OutBroadcast || chat.typ == Chattype::InBroadcast {
|
if chat.typ == Chattype::OutBroadcast || chat.typ == Chattype::InBroadcast {
|
||||||
headers.push((
|
headers.push((
|
||||||
"List-ID",
|
"List-ID",
|
||||||
@@ -799,6 +799,15 @@ impl MimeFactory {
|
|||||||
))
|
))
|
||||||
.into(),
|
.into(),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
if msg.param.get_cmd() == SystemMessage::MemberAddedToGroup {
|
||||||
|
if let Some(secret) = chat.param.get(Param::SymmetricKey) {
|
||||||
|
headers.push((
|
||||||
|
"Chat-Broadcast-Secret",
|
||||||
|
mail_builder::headers::text::Text::new(secret.to_string()).into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -979,6 +988,15 @@ impl MimeFactory {
|
|||||||
} else {
|
} else {
|
||||||
unprotected_headers.push(header.clone());
|
unprotected_headers.push(header.clone());
|
||||||
}
|
}
|
||||||
|
} else if header_name == "chat-broadcast-secret" {
|
||||||
|
if is_encrypted {
|
||||||
|
protected_headers.push(header.clone());
|
||||||
|
} else {
|
||||||
|
warn!(
|
||||||
|
context,
|
||||||
|
"Message is unnecrypted, not including broadcast secret"
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if is_encrypted {
|
} else if is_encrypted {
|
||||||
protected_headers.push(header.clone());
|
protected_headers.push(header.clone());
|
||||||
|
|
||||||
|
|||||||
@@ -169,7 +169,9 @@ pub enum Param {
|
|||||||
/// post something to the mailing list.
|
/// post something to the mailing list.
|
||||||
ListPost = b'p',
|
ListPost = b'p',
|
||||||
|
|
||||||
/// For Chats of type [`Chattype::OutBroadcast`] and [`Chattype::InBroadcast`]: // TODO (or just OutBroadcast)
|
/// For Chats and Messages:
|
||||||
|
/// For chats of type [`Chattype::OutBroadcast`] and [`Chattype::InBroadcast`] // TODO (or just OutBroadcast)
|
||||||
|
/// and for messages adding members to such a chat.
|
||||||
/// The symmetric key shared among all chat participants,
|
/// The symmetric key shared among all chat participants,
|
||||||
/// used to encrypt and decrypt messages.
|
/// used to encrypt and decrypt messages.
|
||||||
SymmetricKey = b'z',
|
SymmetricKey = b'z',
|
||||||
|
|||||||
19
src/tools.rs
19
src/tools.rs
@@ -300,6 +300,25 @@ pub(crate) fn create_id() -> String {
|
|||||||
base64::engine::general_purpose::URL_SAFE.encode(arr)
|
base64::engine::general_purpose::URL_SAFE.encode(arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate a shared secret for a broadcast channel, consisting of 64 characters..
|
||||||
|
///
|
||||||
|
/// The string generated by this function has 384 bits of entropy
|
||||||
|
/// and is returned as 64 Base64 characters, each containing 6 bits of entropy.
|
||||||
|
/// 384 is chosen because it is sufficiently secure
|
||||||
|
/// (larger than AES-128 keys used for message encryption)
|
||||||
|
/// and divides both by 8 (byte size) and 6 (number of bits in a single Base64 character).
|
||||||
|
// TODO ask someone what a good size would be here
|
||||||
|
pub(crate) fn create_broadcast_shared_secret() -> String {
|
||||||
|
// ThreadRng implements CryptoRng trait and is supposed to be cryptographically secure.
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
|
||||||
|
// Generate 384 random bits.
|
||||||
|
let mut arr = [0u8; 48];
|
||||||
|
rng.fill(&mut arr[..]);
|
||||||
|
|
||||||
|
base64::engine::general_purpose::URL_SAFE.encode(arr)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if given string is a valid ID.
|
/// Returns true if given string is a valid ID.
|
||||||
///
|
///
|
||||||
/// All IDs generated with `create_id()` should be considered valid.
|
/// All IDs generated with `create_id()` should be considered valid.
|
||||||
|
|||||||
Reference in New Issue
Block a user