feat: Increase secret size to 256 bits of entropy

This is for quantumn computers. When trying to break AES, quantumn
computers give a square-root speedup, i.e. the 144 bits of entropy would
take as many queries as breaking 72 bits of entropy on a normal computer. This neglects
e.g. the costs of quantumn circuits and quantumn error correction [1], so,
144 bits entropy would actually have been fine, but in order to be on
the very safe side and so that noone can complain, let's increase it to
256 bits.

[1]: https://csrc.nist.gov/csrc/media/Events/2024/fifth-pqc-standardization-conference/documents/papers/on-practical-cost-of-grover.pdf
This commit is contained in:
Hocuri
2025-08-04 17:17:49 +02:00
parent 13bbcbeb0e
commit 494ad63a73
4 changed files with 32 additions and 8 deletions

View File

@@ -43,9 +43,9 @@ use crate::smtp::send_msg_to_smtp;
use crate::stock_str;
use crate::sync::{self, Sync::*, SyncData};
use crate::tools::{
IsNoneOrEmpty, SystemTime, buf_compress, create_id, create_outgoing_rfc724_mid,
create_smeared_timestamp, create_smeared_timestamps, get_abs_path, gm2local_offset,
smeared_time, time, truncate_msg_text,
IsNoneOrEmpty, SystemTime, buf_compress, create_broadcast_shared_secret, create_id,
create_outgoing_rfc724_mid, create_smeared_timestamp, create_smeared_timestamps, get_abs_path,
gm2local_offset, smeared_time, time, truncate_msg_text,
};
use crate::webxdc::StatusUpdateSerial;
use crate::{chatlist_events, imap};
@@ -3794,7 +3794,7 @@ pub async fn create_group_ex(
/// Returns the created chat's id.
pub async fn create_broadcast(context: &Context, chat_name: String) -> Result<ChatId> {
let grpid = create_id();
let secret = create_id();
let secret = create_broadcast_shared_secret();
create_broadcast_ex(context, Sync, grpid, chat_name, secret).await
}

View File

@@ -20,7 +20,7 @@ use crate::message::Message;
use crate::net::http::post_empty;
use crate::net::proxy::{DEFAULT_SOCKS_PORT, ProxyConfig};
use crate::token;
use crate::tools::validate_id;
use crate::tools::{validate_broadcast_shared_secret, validate_id};
const OPENPGP4FPR_SCHEME: &str = "OPENPGP4FPR:"; // yes: uppercase
const IDELTACHAT_SCHEME: &str = "https://i.delta.chat/#";
@@ -459,7 +459,7 @@ async fn decode_openpgp(context: &Context, qr: &str) -> Result<Qr> {
.map(|s| s.to_string());
let broadcast_shared_secret = param
.get("b")
.filter(|&s| validate_id(s))
.filter(|&s| validate_broadcast_shared_secret(s))
.map(|s| s.to_string());
let grpname = if grpid.is_some() {

View File

@@ -44,7 +44,7 @@ use crate::securejoin::{self, handle_securejoin_handshake, observe_securejoin_on
use crate::simplify;
use crate::stock_str;
use crate::sync::Sync::*;
use crate::tools::{self, buf_compress, create_id, remove_subject_prefix};
use crate::tools::{self, buf_compress, create_broadcast_shared_secret, remove_subject_prefix};
use crate::{chatlist_events, ensure_and_debug_assert, ensure_and_debug_assert_eq, location};
use crate::{contact, imap};
@@ -1566,7 +1566,7 @@ async fn do_chat_assignment(
} else {
let name =
compute_mailinglist_name(mailinglist_header, &listid, mime_parser);
let secret = create_id();
let secret = create_broadcast_shared_secret();
chat::create_broadcast_ex(context, Nosync, listid, name, secret).await?
},
);

View File

@@ -300,6 +300,25 @@ pub(crate) fn create_id() -> String {
base64::engine::general_purpose::URL_SAFE.encode(arr)
}
/// Generate a shared secret for a broadcast channel, consisting of 43 characters.
///
/// The string generated by this function has 258 bits of entropy
/// and is returned as 43 Base64 characters, each containing 6 bits of entropy.
/// 256 is chosen because we may switch to AES-256 keys in the future,
/// and so that the shared secret definitely won't be the weak spot.
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 264 random bits.
let mut arr = [0u8; 33];
rng.fill(&mut arr[..]);
let mut res = base64::engine::general_purpose::URL_SAFE.encode(arr);
res.truncate(43);
res
}
/// Returns true if given string is a valid ID.
///
/// All IDs generated with `create_id()` should be considered valid.
@@ -308,6 +327,11 @@ pub(crate) fn validate_id(s: &str) -> bool {
s.chars().all(|c| alphabet.contains(c)) && s.len() > 10 && s.len() <= 32
}
pub(crate) fn validate_broadcast_shared_secret(s: &str) -> bool {
let alphabet = base64::alphabet::URL_SAFE.as_str();
s.chars().all(|c| alphabet.contains(c)) && s.len() == 43
}
/// Function generates a Message-ID that can be used for a new outgoing message.
/// - this function is called for all outgoing messages.
/// - the message ID should be globally unique