Commit Graph

101 Commits

Author SHA1 Message Date
link2xt
598d759b8d refactor(imex): check for overflow when adding blob size
Cannot happen without custom filesystem or sparse files,
but removes clippy lint.
2026-02-17 16:01:16 +00:00
link2xt
10b93b3943 refactor: enable clippy::arithmetic_side_effects lint 2026-02-17 16:01:16 +00:00
link2xt
cf5b145ce0 refactor: remove unused imports 2025-11-07 17:31:34 +00:00
Hocuri
5034449009 feat!: QR codes and symmetric encryption for broadcast channels (#7268)
Follow-up for https://github.com/chatmail/core/pull/7042, part of
https://github.com/chatmail/core/issues/6884.

This will make it possible to create invite-QR codes for broadcast
channels, and make them symmetrically end-to-end encrypted.

- [x] Go through all the changes in #7042, and check which ones I still
need, and revert all other changes
- [x] Use the classical Securejoin protocol, rather than the new 2-step
protocol
- [x] Make the Rust tests pass
- [x] Make the Python tests pass
- [x] Fix TODOs in the code
- [x] Test it, and fix any bugs I find
- [x] I found a bug when exporting all profiles at once fails sometimes,
though this bug is unrelated to channels:
https://github.com/chatmail/core/issues/7281
- [x] Do a self-review (i.e. read all changes, and check if I see some
things that should be changed)
- [x] Have this PR reviewed and merged
- [ ] Open an issue for "TODO: There is a known bug in the securejoin
protocol"
- [ ] Create an issue that outlines how we can improve the Securejoin
protocol in the future (I don't have the time to do this right now, but
want to do it sometime in winter)
- [ ] Write a guide for UIs how to adapt to the changes (see
https://github.com/deltachat/deltachat-android/pull/3886)

## Backwards compatibility

This is not very backwards compatible:
- Trying to join a symmetrically-encrypted broadcast channel with an old
device will fail
- If you joined a symmetrically-encrypted broadcast channel with one
device, and use an old core on the other device, then the other device
will show a mostly empty chat (except for two device messages)
- If you created a broadcast channel in the past, then you will get an
error message when trying to send into the channel:

> The up to now "experimental channels feature" is about to become an officially supported one. By that, privacy will be improved, it will become faster, and less traffic will be consumed.
> 
> As we do not guarantee feature-stability for such experiments, this means, that you will need to create the channel again. 
> 
> Here is what to do:
>  • Create a new channel
>  • Tap on the channel name
>  • Tap on "QR Invite Code"
>  • Have all recipients scan the QR code, or send them the link
> 
> If you have any questions, please send an email to delta@merlinux.eu or ask at https://support.delta.chat/.


## The symmetric encryption

Symmetric encryption uses a shared secret. Currently, we use AES128 for
encryption everywhere in Delta Chat, so, this is what I'm using for
broadcast channels (though it wouldn't be hard to switch to AES256).

The secret shared between all members of a broadcast channel has 258
bits of entropy (see `fn create_broadcast_shared_secret` in the code).

Since the shared secrets have more entropy than the AES session keys,
it's not necessary to have a hard-to-compute string2key algorithm, so,
I'm using the string2key algorithm `salted`. This is fast enough that
Delta Chat can just try out all known shared secrets. [^1] In order to
prevent DOS attacks, Delta Chat will not attempt to decrypt with a
string2key algorithm other than `salted` [^2].

## The "Securejoin" protocol that adds members to the channel after they
scanned a QR code

This PR uses the classical securejoin protocol, the same that is also
used for group and 1:1 invitations.

The messages sent back and forth are called `vg-request`,
`vg-auth-required`, `vg-request-with-auth`, and `vg-member-added`. I
considered using the `vc-` prefix, because from a protocol-POV, the
distinction between `vc-` and `vg-` isn't important (as @link2xt pointed
out in an in-person discussion), but
1. it would be weird if groups used `vg-` while broadcasts and 1:1 chats
used `vc-`,
2. we don't have a `vc-member-added` message yet, so, this would mean
one more different kind of message
3. we anyways want to switch to a new securejoin protocol soon, which
will be a backwards incompatible change with a transition phase. When we
do this change, we can make everything `vc-`.



[^1]: In a symmetrically encrypted message, it's not visible which
secret was used to encrypt without trying out all secrets. If this does
turn out to be too slow in the future, then we can remember which secret
was used more recently, and and try the most recent secret first. If
this is still too slow, then we can assign a short, non-unique (~2
characters) id to every shared secret, and send it in cleartext. The
receiving Delta Chat will then only try out shared secrets with this id.
Of course, this would leak a little bit of metadata in cleartext, so, I
would like to avoid it.
[^2]: A DOS attacker could send a message with a lot of encrypted
session keys, all of which use a very hard-to-compute string2key
algorithm. Delta Chat would then try to decrypt all of the encrypted
session keys with all of the known shared secrets. In order to prevent
this, as I said, Delta Chat will not attempt to decrypt with a
string2key algorithm other than `salted`

BREAKING CHANGE: A new QR type AskJoinBroadcast; cloning a broadcast
channel is no longer possible; manually adding a member to a broadcast
channel is no longer possible (only by having them scan a QR code)
2025-11-03 21:02:13 +01:00
link2xt
f428033d95 build: update rand to 0.9
We already have both rand 0.8 and rand 0.9
in our dependency tree.

We still need rand 0.8 because
public APIs of rPGP 0.17.0 and Iroh 0.35.0
use rand 0.8 types in public APIs,
so it is imported as rand_old.
2025-10-26 07:08:54 +00:00
link2xt
38e4919be1 api!: consistent spelling of "canceled" with a single "l"
This is how it is spelled in iOS UI and Android APIs.
2025-10-02 11:19:48 +00:00
link2xt
d4704977bc api!: remove e2ee_enabled preference
The setting is already removed from the UIs,
but users who had it disabled previously have
no way to enable it. After this change
encryption is effectively always preferred.
2025-09-04 13:58:05 +00:00
iequidoo
6837874d43 fix: get_connectivity(): Get rid of locking SchedulerState::inner (#7124)
`get_connectivity()` is expected to return immediately, not when the scheduler finishes updating its
state in `start_io()/stop_io()/pause_io()`, otherwise it causes app non-responsiveness.

Instead of read-locking `SchedulerState::inner`, store the `ConnectivityStore` collection in
`Context` and fetch it from there in `get_connectivity()`. Update it every time we release a write
lock on `SchedulerState::inner`.
2025-08-22 14:18:30 -03:00
bjoern
6c536f3a9b fix: log and set imex progress error (#7091)
IMEX_PROGRESS(0) event is fired in case of errors, however, the last
error was not set in this case.

this is similar to the fix at #4195
and improves the error shown in the dialog for android and iOS; desktop
does not show an error dialog at all.

<img width="320" alt="IMG_9995"
src="https://github.com/user-attachments/assets/7065fc3d-3f30-4691-b1b2-1950564a25e2"
/>

relates to https://github.com/deltachat/deltachat-android/issues/3533
2025-08-09 01:17:27 +02:00
link2xt
5c3de759d3 refactor: upgrade to Rust 2024 2025-06-28 17:07:59 +00:00
link2xt
416131b4a2 feat: key-contacts
This change introduces a new type of contacts
identified by their public key fingerprint
rather than an e-mail address.

Encrypted chats now stay encrypted
and unencrypted chats stay unencrypted.
For example, 1:1 chats with key-contacts
are encrypted and 1:1 chats with address-contacts
are unencrypted.
Groups that have a group ID are encrypted
and can only contain key-contacts
while groups that don't have a group ID ("adhoc groups")
are unencrypted and can only contain address-contacts.

JSON-RPC API `reset_contact_encryption` is removed.
Python API `Contact.reset_encryption` is removed.
"Group tracking plugin" in legacy Python API was removed because it
relied on parsing email addresses from system messages with regexps.

Co-authored-by: Hocuri <hocuri@gmx.de>
Co-authored-by: iequidoo <dgreshilov@gmail.com>
Co-authored-by: B. Petersen <r10s@b44t.com>
2025-06-26 14:07:39 +00:00
link2xt
545007aca5 api!: make logging macros private 2025-06-21 11:01:25 +00:00
Friedel Ziegelmayer
5c2af42cdd build: update to rPGP 0.16.0 (#6719)
Co-authored-by: Heiko Schaefer <heiko@schaefer.name>
Co-authored-by: link2xt <link2xt@testrun.org>
2025-05-29 13:06:18 +00:00
l
6661a0803e chore: update iroh from 0.33.0 to 0.35.0 (#6687) 2025-05-12 20:33:21 +00:00
Sebastian Klähn
846c8e7f1b Generate rfc724_mid when creating Message (#6704)
Set `rfc724_mid` in `Message::new()`, `Message::new_text()`, and
`Message::default()` instead of when sending the message. This way the
rfc724 mid can be read in the draft stage which makes it more consistent
for bots. Tests had to be adjusted to create multiple messages to get
unique mid, otherwise core would not send the messages out.
2025-05-05 15:06:05 +00:00
bjoern
de5cbd3de3 move ASM strings to core, point to "Add Second Device" (#6777)
this PR moves now advanced/unsupported ASM strings to core, removing
work from translations, esp. as another hint is added which would
require retranslations. it is better to have that just in english, it is
a nerd feature anyways.

moverover, this PR removes special rendering of ASM in the summary,
which might be confusion, but mainly it is now unneeded, dead code

i'll do another android PR that will point to "Add Second Device"
already on ASM generation EDIT: done at
https://github.com/deltachat/deltachat-android/pull/3726

targets https://github.com/deltachat/deltachat-desktop/issues/4946
2025-04-07 18:44:41 +00:00
iequidoo
5d334ee6ee fix: Don't SMTP-send self-only messages if DeleteServerAfter is "immediate" (#6661) 2025-03-18 00:38:21 -03:00
Hocuri
dc17f2692c fix: Fix setting up a profile and immediately transferring to a second device (#6657)
Found and fixed a bug while investigating
https://github.com/chatmail/core/issues/6656. It's not the same bug,
though.

Steps to reproduce this bug:
- Create a new profile
- Transfer it to a second device
- Send a message from the first device
- -> It will never arrive on the second device, instead a warning will
be printed that you are using DC on multiple devices.

The bug was that the key wasn't created before the backup transfer, so
that the second device then created its own key instead of using the
same key as the first device.

In order to regression-test, this PR now changes `clone()` to use "Add
second device" instead of exporting and importing a backup. Exporting
and importing a backup has enough tests already.

This PR also adds an unrelated test `test_selfavatar_sync()`.

The bug was introduced by https://github.com/chatmail/core/pull/6574 in
v1.156.0
2025-03-17 18:12:35 +01:00
link2xt
8c2207d15e fix: make it impossible to overwrite default key
Replacing default key
when a profile is already part of
verified groups results in
`[The message was sent with non-verified encryption. See 'Info' for more details]`
messages for other users.

It is still possible
to import the default key before
Delta Chat generates the key.
2025-02-26 20:56:52 +00:00
link2xt
b916937a7a feat: enable bcc-self automatically when doing Autocrypt Setup Message 2025-02-22 23:47:36 +00:00
dignifiedquire
5bde9b66d1 feat: upgrade to iroh@0.30.0 2025-01-28 03:26:57 +00:00
Hocuri
3959305b4a feat: Deduplicate in more places (#6464)
Deduplicate:
- In the REPL
- In `store_from_base64()`, which writes avatars received in headers
- In a few tests
- The saved messages, broadcast, device, archive icons
- The autocrypt setup message

1-2 more PRs, and we can get rid of `BlobObject::create`,
`sanitise_name()`, and some others
2025-01-22 20:39:18 +00:00
Hocuri
8f58c4777e feat: Keep file extension on deduplicated files (#6463)
fix #6461
2025-01-22 16:44:59 +01:00
Hocuri
65a9c4b79b File deduplication (#6332)
When receiving messages, blobs will be deduplicated with the new
function `create_and_deduplicate_from_bytes()`. For sending files, this
adds a new function `set_file_and_deduplicate()` instead of
deduplicating by default.

This is for
https://github.com/deltachat/deltachat-core-rust/issues/6265; read the
issue description there for more details.

TODO:
- [x] Set files as read-only
- [x] Don't do a write when the file is already identical
- [x] The first 32 chars or so of the 64-character hash are enough. I
calculated that if 10b people (i.e. all of humanity) use DC, and each of
them has 200k distinct blob files (I have 4k in my day-to-day account),
and we used 20 chars, then the expected value for the number of name
collisions would be ~0.0002 (and the probability that there is a least
one name collision is lower than that) [^1]. I added 12 more characters
to be on the super safe side, but this wouldn't be necessary and I could
also make it 20 instead of 32.
- Not 100% sure whether that's necessary at all - it would mainly be
necessary if we might hit a length limit on some file systems (the
blobdir is usually sth like
`accounts/2ff9fc096d2f46b6832b24a1ed99c0d6/dc.db-blobs` (53 chars), plus
64 chars for the filename would be 117).
- [x] "touch" the files to prevent them from being deleted
- [x] TODOs in the code

For later PRs:
- Replace `BlobObject::create(…)` with
`BlobObject::create_and_deduplicate(…)` in order to deduplicate
everytime core creates a file
- Modify JsonRPC to deduplicate blob files
- Possibly rename BlobObject.name to BlobObject.file in order to prevent
confusion (because `name` usually means "user-visible-name", not "name
of the file on disk").

[^1]: Calculated with both https://printfn.github.io/fend/ and
https://www.geogebra.org/calculator, both of which came to the same
result
([1](https://github.com/user-attachments/assets/bbb62550-3781-48b5-88b1-ba0e29c28c0d),

[2](https://github.com/user-attachments/assets/82171212-b797-4117-a39f-0e132eac7252))

---------

Co-authored-by: l <link2xt@testrun.org>
2025-01-21 19:42:19 +01:00
iequidoo
3af4ea1d00 feat: Emit ImexProgress(1) after receiving backup size
UIs may want to display smth like "Transferring..." after "Establishing connection between
devices..." on nonzero progress. Before, progress on the receiver side was starting with 2 after
receiving enough data.
2024-12-17 21:12:09 -03:00
Hocuri
d6c2c863b7 refactor: Use Message::new_text() more (#6127)
Follow-up to https://github.com/deltachat/deltachat-core-rust/pull/6123
2024-10-30 12:05:58 +00:00
link2xt
2cb8b53256 fix: emit progress 0 if get_backup() fails 2024-10-05 17:58:24 +00:00
link2xt
a592a470cf fix: make backup reception cancellable by stopping ongoing process
This is already documented in JSON-RPC API,
but in fact ongoing process was not allocated.
2024-10-05 17:58:24 +00:00
link2xt
c4d07ab99e fix: smooth progress bar for backup transfer
Before this change progress bar only started
when database is already transferred.
Database is usually the largest file
in the whole transfer, so the transfer appears
to be stuck for the sender.

With this change progress bar
starts for backup export
as soon as connection is received
and counts bytes transferred over the connection
using AsyncWrite wrapper.

Similarly for backup import,
AsyncRead wrapper counts the bytes
received and emits progress events.
2024-10-05 17:58:24 +00:00
link2xt
eddd5a0d25 fix: make it possible to cancel ongoing backup transfer 2024-10-05 17:58:24 +00:00
link2xt
0f43d5d8f4 fix: break out of accept() loop if there is an error transferring backup 2024-10-05 17:58:24 +00:00
link2xt
b47b96d5d6 chore(cargo): update iroh to 0.25
According to
<https://www.iroh.computer/blog/iroh-0-25-0-custom-protocols-for-all>
gossip now handles updating direct addresses automatically.
2024-09-20 22:56:24 +00:00
link2xt
54cfc21e28 Remove old iroh 0.4 2024-08-29 20:59:41 +00:00
link2xt
d6d90db957 feat: new BACKUP2 transfer protocol
New protocol streams .tar into iroh-net
stream without traversing all the files first.
Reception over old backup protocol
is still supported to allow
transferring backups from old devices
to new ones, but not vice versa.
2024-07-19 03:16:57 +00:00
link2xt
d77459e4fc refactor: move TempPathGuard into tools and use instead of DeleteOnDrop 2024-07-10 20:13:42 +00:00
link2xt
2c14bd353f refactor: move key transfer into its own submodule
`create_setup_code` and `render_setup_file`
are now hidden from public API,
so deltachat-repl does not have "export-setup"
debug command anymore.
2024-07-10 04:29:10 +00:00
Sebastian Klähn
36f1fc4f9d feat: ephemeral peer channels (#5346)
Co-authored-by: link2xt <link2xt@testrun.org>
Co-authored-by: iequidoo <117991069+iequidoo@users.noreply.github.com>
2024-05-17 20:13:21 +00:00
iequidoo
56b86adf18 api: Add dc_msg_save_file() which saves file copy at the provided path (#4309)
... and fails if file already exists. The UI should open the file saving dialog, defaulting to
Downloads and original filename, when asked to save the file. After confirmation it should call
dc_msg_save_file().
2024-04-24 16:38:25 -03:00
link2xt
2030de11d9 chore: fix 2024-03-05 nightly clippy warnings 2024-03-08 02:53:47 +00:00
iequidoo
fe3c1f69c3 feat: Cache system time instead of looking at the clock several times in a row
The system clock may be adjusted and even go back, so caching system time in code sections where
it's not supposed to change may even protect from races/bugs.
2024-02-12 21:13:36 -03:00
link2xt
2f8a8f9f50 ci: update to Rust 1.75.0 and fix clippy 2024-01-08 20:01:40 +00:00
iequidoo
55aaec744a feat: Make dc_msg_get_filename() return the original attachment filename (#4309)
It can be used e.g. as a default in the file saving dialog. Also display the original filename in
the message info. For these purposes add Param::Filename in addition to Param::File and use it as an
attachment filename in sent emails.
2023-07-27 14:31:14 -03:00
link2xt
9c68fac4b6 api!: make Message.text non-optional
Message.set_text() and Message.get_text() are modified accordingly
to accept String and return String.

Messages which previously contained None text
are now represented as messages with empty text.
Use Message.set_text("".to_string())
instead of Message.set_text(None).
2023-07-03 15:36:32 +00:00
Hocuri
a806a218bf Clippy; remove forgotten dbg! (#4338) 2023-04-18 18:52:01 +00:00
link2xt
d2fb2bb2ca Merge 1.112.7 into master 2023-04-17 15:24:15 +00:00
Floris Bruynooghe
86c18fb3ae ref: More logging for ongoing and get_backup (#4289)
This adds a few log items for imex::transfer::get_backup and the
ongoing process to give some more insights.

IO is now also paused after the ongoing process is allocated in
get_backup to avoid needlessly pausing IO.
2023-04-04 18:11:45 +02:00
link2xt
2ba4381c39 Merge branch 'stable-1.112' into 'master' 2023-04-04 15:01:37 +00:00
B. Petersen
a1f112470e add a device message when backup transfer ends
that way, UI can just close the transfer dialog,
so that, at the end, both devices end in the chatlist.

we can also use this for troubleshooting -
if the device message is not present,
transfer did not succeed completely.

(a separate device message may be nice in that case -
but that is another effort,
same for making the device message reappear after deletion
or after some time)
2023-04-04 14:17:26 +02:00
Floris Bruynooghe
c6c20d8f3c ref(scheduler): Make InnerSchedulerState an enum (#4251)
This is more verbose, but makes reasoning about things easier.
2023-04-03 11:13:44 +02:00
link2xt
f6d27516cb Run migrations before delete_and_reset_all_device_msgs()
Both when importing a backup from file or receiving it over the network.
2023-04-02 08:39:13 +00:00