Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
9694ba3
[WIP] QR codes and symmetric encryption for broadcast channels
Hocuri Oct 2, 2025
10091a7
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 2, 2025
62d7441
test: Fix test_broadcast_multidev
Hocuri Oct 2, 2025
a434e6e
Fix some things, so that all tests pass sometimes. Some tests are sti…
Hocuri Oct 6, 2025
7f3d0cc
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 6, 2025
17fdac2
clippy
Hocuri Oct 6, 2025
8b3b597
test: Fix the flaky tests. All tests pass now!
Hocuri Oct 6, 2025
915bad9
refactor: Remove unused MarkVerified sync action
Hocuri Oct 7, 2025
d755f61
improve comment
Hocuri Oct 7, 2025
e001067
Some things I noticed while self-reviewing
Hocuri Oct 7, 2025
c602586
Small comment improvements
Hocuri Oct 7, 2025
7d92fcd
fix: Don't invent a secret when receiving an outgoing broadcast message
Hocuri Oct 7, 2025
faa149a
small comment improvement
Hocuri Oct 8, 2025
5a91887
more comment improvements
Hocuri Oct 8, 2025
41b4953
more tweaks
Hocuri Oct 8, 2025
6114a6a
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 8, 2025
27d1d35
small tweaks
Hocuri Oct 8, 2025
89f1e52
clippy
Hocuri Oct 8, 2025
7fcbf39
Simon's review
Hocuri Oct 15, 2025
e00db35
Merge branch 'main' into hoc/channels-encryption-3
Hocuri Oct 15, 2025
a3a932a
clippy
Hocuri Oct 15, 2025
7bd1ced
Update src/securejoin/bob.rs
Hocuri Oct 20, 2025
07a6062
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 20, 2025
e6bb254
Update golden tests
Hocuri Oct 20, 2025
24cbcbe
fix: Don't add duplicate member-added message
Hocuri Oct 21, 2025
691887f
iequidoo's review
Hocuri Oct 21, 2025
e74f312
clippy
Hocuri Oct 21, 2025
fcc3363
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 21, 2025
f336add
iequidoo's review
Hocuri Oct 23, 2025
24d5335
Fix compilation error
Hocuri Oct 23, 2025
a836775
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 23, 2025
8a4044e
Another compilation error
Hocuri Oct 23, 2025
1d671d2
Fix test
Hocuri Oct 23, 2025
cafc2c7
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 23, 2025
efc323f
fix: Show an error message when trying to send into an old channel
Hocuri Oct 23, 2025
ab1844d
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 24, 2025
9776cd7
refactor: rename broadcast_shared_secret -> broadcast_secret
Hocuri Oct 25, 2025
745d38c
refactor: inline handle_sync_create_chat()
Hocuri Oct 25, 2025
1029707
Bail if added/removed member is missing
Hocuri Oct 25, 2025
205ca0f
refactor: Rename src/internals_for_benchmarks.rs -> src/internals_for…
Hocuri Oct 26, 2025
4d615d6
comments
Hocuri Oct 26, 2025
9f87a53
Make some code shorter
Hocuri Oct 26, 2025
c101f2a
Small changes from iequidoo's review
Hocuri Oct 26, 2025
93b8763
more of iequidoo's suggestions
Hocuri Oct 26, 2025
ea82fe9
Rename encryption_keys -> encryption_pubkeys
Hocuri Oct 26, 2025
0e0c534
clippy
Hocuri Oct 26, 2025
9e9ed67
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 26, 2025
501b5a7
remaining review comments
Hocuri Oct 26, 2025
9e0ff87
more review
Hocuri Oct 28, 2025
717d6bb
review, again
Hocuri Oct 28, 2025
0a69a55
Make all rust tests pass again
Hocuri Oct 28, 2025
7fdee26
clippy
Hocuri Oct 28, 2025
1a85ad7
Update src/test_utils.rs
Hocuri Oct 28, 2025
05cacc0
small test improvements
Hocuri Oct 28, 2025
9048977
feat: Add and use stock string "You joined the channel"
Hocuri Oct 28, 2025
bd12139
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 28, 2025
c3be22f
Update src/mimefactory.rs
Hocuri Oct 28, 2025
bc116bd
fix compilation
Hocuri Oct 28, 2025
d9e38c6
Try to fix Python tests
Hocuri Oct 28, 2025
c71f698
fix: Delete broadcast secret when leaving or being removed from channel
Hocuri Oct 28, 2025
dd3cffd
don't prematurely optimize SQL statement
Hocuri Oct 28, 2025
7be7ba0
feat: If someone who is not the admin tries to send into brodacast, a…
Hocuri Oct 29, 2025
1d3ae6d
small fixes
Hocuri Oct 29, 2025
327e0cc
test: Fix test flakiness
Hocuri Oct 29, 2025
af20e3e
fix: Delete request-with-auth messages immediately; some tests still …
Hocuri Oct 29, 2025
ca986cc
Update src/receive_imf.rs
Hocuri Oct 31, 2025
644d6e5
fix: stop using `leftgrps` table
link2xt Oct 28, 2025
1bbd3ec
feat(backwards-compat): For now, send Chat-Verified header (instead o…
Hocuri Oct 29, 2025
3723cd1
fix remaining test failures
Hocuri Oct 31, 2025
c1b53b1
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Oct 31, 2025
c0aa31c
fix: Set chat_created = true when creating outgoing broadcast
Hocuri Oct 31, 2025
2409431
Merge remote-tracking branch 'origin/main' into hoc/channels-encrypti…
Hocuri Nov 1, 2025
28d1ca9
fix: Use Chat-List-Id rather than List-Id header
Hocuri Nov 1, 2025
36a8f20
fix: Make sure broadcast members can't see each other
Hocuri Nov 3, 2025
8b300b8
fix: Use j= instead of i= in broadcast invites, so that old devices d…
Hocuri Nov 3, 2025
788765f
Fix compilation error
Hocuri Nov 3, 2025
47b8a2d
iequidoo's review
Hocuri Nov 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refactor: rename broadcast_shared_secret -> broadcast_secret
  • Loading branch information
Hocuri committed Oct 25, 2025
commit 9776cd79ff8b90addd8b63a621511bc7dfbc11a6
8 changes: 4 additions & 4 deletions benches/benchmark_decrypting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
use std::hint::black_box;

use criterion::{Criterion, criterion_group, criterion_main};
use deltachat::internals_for_benchmarks::create_broadcast_shared_secret;
use deltachat::internals_for_benchmarks::create_broadcast_secret;
use deltachat::internals_for_benchmarks::create_dummy_keypair;
use deltachat::internals_for_benchmarks::save_broadcast_shared_secret;
use deltachat::internals_for_benchmarks::save_broadcast_secret;
use deltachat::{
Events,
chat::ChatId,
Expand Down Expand Up @@ -142,7 +142,7 @@ fn criterion_benchmark(c: &mut Criterion) {
let context = rt.block_on(async {
let context = create_context().await;
for (i, secret) in secrets.iter().enumerate() {
save_broadcast_shared_secret(&context, ChatId::new(10 + i as u32), secret)
save_broadcast_secret(&context, ChatId::new(10 + i as u32), secret)
.await
.unwrap();
}
Expand Down Expand Up @@ -184,7 +184,7 @@ fn criterion_benchmark(c: &mut Criterion) {

fn generate_secrets() -> Vec<String> {
let secrets: Vec<String> = (0..NUM_SECRETS)
.map(|_| create_broadcast_shared_secret())
.map(|_| create_broadcast_secret())
.collect();
secrets
}
Expand Down
14 changes: 7 additions & 7 deletions src/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ 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_broadcast_shared_secret, create_id,
IsNoneOrEmpty, SystemTime, buf_compress, create_broadcast_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};

pub(crate) const PARAM_BROADCAST_SHARED_SECRET: Param = Param::Arg3;
pub(crate) const PARAM_BROADCAST_SECRET: Param = Param::Arg3;

/// An chat item, such as a message or a marker.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -3496,7 +3496,7 @@ pub(crate) 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_broadcast_shared_secret();
let secret = create_broadcast_secret();
create_out_broadcast_ex(context, Sync, grpid, chat_name, secret).await
}

Expand Down Expand Up @@ -3552,7 +3552,7 @@ pub(crate) async fn create_out_broadcast_ex(
Ok(chat_id)
}

pub(crate) async fn load_broadcast_shared_secret(
pub(crate) async fn load_broadcast_secret(
context: &Context,
chat_id: ChatId,
) -> Result<Option<String>> {
Expand All @@ -3565,7 +3565,7 @@ pub(crate) async fn load_broadcast_shared_secret(
.await
}

pub(crate) async fn save_broadcast_shared_secret(
pub(crate) async fn save_broadcast_secret(
context: &Context,
chat_id: ChatId,
secret: &str,
Expand Down Expand Up @@ -3789,10 +3789,10 @@ pub(crate) async fn add_contact_to_chat_ex(
msg.param
.set_int(Param::ContactAddedRemoved, contact.id.to_u32() as i32);
if chat.typ == Chattype::OutBroadcast {
let secret = load_broadcast_shared_secret(context, chat_id)
let secret = load_broadcast_secret(context, chat_id)
.await?
.context("Failed to find broadcast shared secret")?;
msg.param.set(PARAM_BROADCAST_SHARED_SECRET, secret);
msg.param.set(PARAM_BROADCAST_SECRET, secret);
}
send_msg(context, chat_id, &mut msg).await?;

Expand Down
6 changes: 3 additions & 3 deletions src/chat/chat_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3258,7 +3258,7 @@ async fn test_only_broadcast_owner_can_send_1() -> Result<()> {
);

Comment thread
Hocuri marked this conversation as resolved.
assert!(
load_broadcast_shared_secret(bob, bob_broadcast_id)
load_broadcast_secret(bob, bob_broadcast_id)
.await?
.is_none()
);
Expand Down Expand Up @@ -3288,7 +3288,7 @@ async fn test_only_broadcast_owner_can_send_2() -> Result<()> {
let bob_broadcast_id = tcm.exec_securejoin_qr(bob, alice, &qr).await;

assert!(
load_broadcast_shared_secret(bob, bob_broadcast_id)
load_broadcast_secret(bob, bob_broadcast_id)
.await?
.is_some()
);
Expand Down Expand Up @@ -3413,7 +3413,7 @@ async fn test_encrypt_decrypt_broadcast() -> Result<()> {
time(),
)
.await?;
save_broadcast_shared_secret(bob, bob_chat_id, secret).await?;
save_broadcast_secret(bob, bob_chat_id, secret).await?;

let sent = alice
.send_text(alice_chat_id, "Symmetrically encrypted message")
Expand Down
12 changes: 4 additions & 8 deletions src/internals_for_benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,14 @@ pub async fn parse_and_get_text(context: &Context, imf_raw: &[u8]) -> Result<Str
Ok(mime_parser.parts.into_iter().next().unwrap().msg)
}

pub async fn save_broadcast_shared_secret(
context: &Context,
chat_id: ChatId,
secret: &str,
) -> Result<()> {
crate::chat::save_broadcast_shared_secret(context, chat_id, secret).await
pub async fn save_broadcast_secret(context: &Context, chat_id: ChatId, secret: &str) -> Result<()> {
crate::chat::save_broadcast_secret(context, chat_id, secret).await
}

pub fn create_dummy_keypair(addr: &str) -> Result<KeyPair> {
pgp::create_keypair(EmailAddress::new(addr)?)
}

pub fn create_broadcast_shared_secret() -> String {
crate::tools::create_broadcast_shared_secret()
pub fn create_broadcast_secret() -> String {
crate::tools::create_broadcast_secret()
}
6 changes: 3 additions & 3 deletions src/mimefactory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use tokio::fs;

use crate::aheader::{Aheader, EncryptPreference};
use crate::blob::BlobObject;
use crate::chat::{self, Chat, PARAM_BROADCAST_SHARED_SECRET, load_broadcast_shared_secret};
use crate::chat::{self, Chat, PARAM_BROADCAST_SECRET, load_broadcast_secret};
use crate::config::Config;
use crate::constants::ASM_SUBJECT;
use crate::constants::{Chattype, DC_FROM_HANDSHAKE};
Expand Down Expand Up @@ -845,7 +845,7 @@ impl MimeFactory {
));

if msg.param.get_cmd() == SystemMessage::MemberAddedToGroup {
if let Some(secret) = msg.param.get(PARAM_BROADCAST_SHARED_SECRET) {
if let Some(secret) = msg.param.get(PARAM_BROADCAST_SECRET) {
headers.push((
"Chat-Broadcast-Secret",
mail_builder::headers::text::Text::new(secret.to_string()).into(),
Expand Down Expand Up @@ -1216,7 +1216,7 @@ impl MimeFactory {
Loaded::Message { chat, msg }
if should_encrypt_with_broadcast_secret(msg, chat) =>
{
let secret = load_broadcast_shared_secret(context, chat.id).await?;
let secret = load_broadcast_secret(context, chat.id).await?;
if secret.is_none() {
// If there is no shared secret yet
// because this is an old broadcast channel,
Expand Down
10 changes: 5 additions & 5 deletions src/receive_imf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use mailparse::SingleInfo;
use num_traits::FromPrimitive;
use regex::Regex;

use crate::chat::{self, Chat, ChatId, ChatIdBlocked, save_broadcast_shared_secret};
use crate::chat::{self, Chat, ChatId, ChatIdBlocked, save_broadcast_secret};
use crate::config::Config;
use crate::constants::{self, Blocked, Chattype, DC_CHAT_ID_TRASH, EDITED_PREFIX, ShowEmails};
use crate::contact::{self, Contact, ContactId, Origin, mark_contact_id_as_verified};
Expand Down Expand Up @@ -43,7 +43,7 @@ use crate::simplify;
use crate::stats::STATISTICS_BOT_EMAIL;
use crate::stock_str;
use crate::sync::Sync::*;
use crate::tools::{self, buf_compress, remove_subject_prefix, validate_broadcast_shared_secret};
use crate::tools::{self, buf_compress, remove_subject_prefix, validate_broadcast_secret};
use crate::{chatlist_events, ensure_and_debug_assert, ensure_and_debug_assert_eq, location};

/// This is the struct that is returned after receiving one email (aka MIME message).
Expand Down Expand Up @@ -1504,7 +1504,7 @@ async fn do_chat_assignment(
compute_mailinglist_name(mailinglist_header, &listid, mime_parser);
if let Some(secret) = mime_parser
.get_header(HeaderDef::ChatBroadcastSecret)
.filter(|s| validate_broadcast_shared_secret(s))
.filter(|s| validate_broadcast_secret(s))
{
chat_id = Some(
chat::create_out_broadcast_ex(
Expand Down Expand Up @@ -3539,8 +3539,8 @@ async fn apply_in_broadcast_changes(
}

if let Some(secret) = mime_parser.get_header(HeaderDef::ChatBroadcastSecret) {
if validate_broadcast_shared_secret(secret) {
save_broadcast_shared_secret(context, chat.id, secret).await?;
if validate_broadcast_secret(secret) {
save_broadcast_secret(context, chat.id, secret).await?;
} else {
warn!(context, "Not saving invalid broadcast secret");
}
Expand Down
4 changes: 2 additions & 2 deletions src/tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ pub(crate) fn create_id() -> String {
/// and is returned as 43 Base64 characters, each containing 6 bits of entropy.
/// 258 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 {
pub(crate) fn create_broadcast_secret() -> String {
// ThreadRng implements CryptoRng trait and is supposed to be cryptographically secure.
let mut rng = thread_rng();
Comment thread
iequidoo marked this conversation as resolved.
Outdated

Expand All @@ -327,7 +327,7 @@ 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 {
pub(crate) fn validate_broadcast_secret(s: &str) -> bool {
let alphabet = base64::alphabet::URL_SAFE.as_str();
s.chars().all(|c| alphabet.contains(c)) && s.len() >= 43 && s.len() <= 100
}
Expand Down