From f6b5c5d15003bca8feaa9a32383bce4ea0c4d826 Mon Sep 17 00:00:00 2001 From: link2xt Date: Fri, 20 Sep 2024 15:04:02 +0000 Subject: [PATCH] feat: generate 144-bit group IDs Instead of generating 72 random bits and reducing them to 66 bits of Base64 characters, generate 144 bits (18 bytes) which is exactly 24 Base64 characters. This should still be accepted by existing Delta Chat clients which expect group ID to be between 11 and 32 characters. Message-ID creation is also simplified to not have `Mr.` prefix and dot in between two IDs. Now it is a single ID followed by `@localhost`. Some outdated documentation comments are removed, e.g. group messages don't start with `Gr.` already. --- src/chat.rs | 11 +++++------ src/tools.rs | 34 +++++++++++++++------------------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/src/chat.rs b/src/chat.rs index 4ee894bf74..a557df6e5b 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -6292,11 +6292,10 @@ mod tests { // Alice has an SMTP-server replacing the `Message-ID:`-header (as done eg. by outlook.com). let sent_msg = alice.pop_sent_msg().await; let msg = sent_msg.payload(); - assert_eq!(msg.match_indices("Message-ID: .@` -/// - for INCOMING messages, the ID is taken from the Chat-Group-ID-header or from the Message-ID in the In-Reply-To: or References:-Header -/// - the group-id should be a string with the characters [a-zA-Z0-9\-_] +/// IDs generated by this function have 144 bits of entropy +/// and are returned as 24 Base64 characters, each containing 6 bits of entropy. +/// 144 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). pub(crate) fn create_id() -> String { // ThreadRng implements CryptoRng trait and is supposed to be cryptographically secure. let mut rng = thread_rng(); - // Generate 72 random bits. - let mut arr = [0u8; 9]; + // Generate 144 random bits. + let mut arr = [0u8; 18]; rng.fill(&mut arr[..]); - // Take 11 base64 characters containing 66 random bits. - base64::engine::general_purpose::URL_SAFE - .encode(arr) - .chars() - .take(11) - .collect() + base64::engine::general_purpose::URL_SAFE.encode(arr) } /// Returns true if given string is a valid ID. @@ -311,7 +307,7 @@ pub(crate) fn validate_id(s: &str) -> bool { /// - the message ID should be globally unique /// - do not add a counter or any private data as this leaks information unnecessarily pub(crate) fn create_outgoing_rfc724_mid() -> String { - format!("Mr.{}.{}@localhost", create_id(), create_id()) + format!("{}@localhost", create_id()) } // the returned suffix is lower-case @@ -925,7 +921,7 @@ DKIM Results: Passed=true"; #[test] fn test_create_id() { let buf = create_id(); - assert_eq!(buf.len(), 11); + assert_eq!(buf.len(), 24); } #[test] @@ -961,7 +957,7 @@ DKIM Results: Passed=true"; #[test] fn test_create_outgoing_rfc724_mid() { let mid = create_outgoing_rfc724_mid(); - assert!(mid.starts_with("Mr.")); + assert_eq!(mid.len(), 34); assert!(mid.ends_with("@localhost")); }