From d4704977bce7296d57113414ea19d6fa0dd68f2e Mon Sep 17 00:00:00 2001 From: link2xt Date: Thu, 4 Sep 2025 05:28:43 +0000 Subject: [PATCH] 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. --- deltachat-ffi/deltachat.h | 1 - src/config.rs | 5 ----- src/context.rs | 2 -- src/e2ee.rs | 6 +----- src/imex.rs | 26 +------------------------- src/imex/key_transfer.rs | 5 +---- src/key.rs | 32 +++++++------------------------- src/mimeparser.rs | 2 +- src/push.rs | 2 +- src/test_utils.rs | 28 +++++++++++----------------- 10 files changed, 23 insertions(+), 86 deletions(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index dee7ded8a..cf8ff0b90 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -415,7 +415,6 @@ char* dc_get_blobdir (const dc_context_t* context); * As for `displayname` and `selfstatus`, also the avatar is sent to the recipients. * To save traffic, however, the avatar is attached only as needed * and also recoded to a reasonable size. - * - `e2ee_enabled` = 0=no end-to-end-encryption, 1=prefer end-to-end-encryption (default) * - `mdns_enabled` = 0=do not send or request read receipts, * 1=send and request read receipts * default=send and request read receipts, only send but not request if `bot` is set diff --git a/src/config.rs b/src/config.rs index b16382cd7..02ad57374 100644 --- a/src/config.rs +++ b/src/config.rs @@ -151,10 +151,6 @@ pub enum Config { /// setting up a second device, or receiving a sync message. BccSelf, - /// True if encryption is preferred according to Autocrypt standard. - #[strum(props(default = "1"))] - E2eeEnabled, - /// True if Message Delivery Notifications (read receipts) should /// be sent and requested. #[strum(props(default = "1"))] @@ -705,7 +701,6 @@ impl Context { Config::Socks5Enabled | Config::ProxyEnabled | Config::BccSelf - | Config::E2eeEnabled | Config::MdnsEnabled | Config::SentboxWatch | Config::MvboxMove diff --git a/src/context.rs b/src/context.rs index ba085f63e..c94780a8d 100644 --- a/src/context.rs +++ b/src/context.rs @@ -833,7 +833,6 @@ impl Context { .query_get_value("PRAGMA journal_mode;", ()) .await? .unwrap_or_else(|| "unknown".to_string()); - let e2ee_enabled = self.get_config_int(Config::E2eeEnabled).await?; let mdns_enabled = self.get_config_int(Config::MdnsEnabled).await?; let bcc_self = self.get_config_int(Config::BccSelf).await?; let sync_msgs = self.get_config_int(Config::SyncMsgs).await?; @@ -967,7 +966,6 @@ impl Context { res.insert("configured_mvbox_folder", configured_mvbox_folder); res.insert("configured_trash_folder", configured_trash_folder); res.insert("mdns_enabled", mdns_enabled.to_string()); - res.insert("e2ee_enabled", e2ee_enabled.to_string()); res.insert("bcc_self", bcc_self.to_string()); res.insert("sync_msgs", sync_msgs.to_string()); res.insert("disable_idle", disable_idle.to_string()); diff --git a/src/e2ee.rs b/src/e2ee.rs index 9968c2245..b68361347 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -4,10 +4,8 @@ use std::io::Cursor; use anyhow::Result; use mail_builder::mime::MimePart; -use num_traits::FromPrimitive; use crate::aheader::{Aheader, EncryptPreference}; -use crate::config::Config; use crate::context::Context; use crate::key::{SignedPublicKey, load_self_public_key, load_self_secret_key}; use crate::pgp; @@ -21,9 +19,7 @@ pub struct EncryptHelper { impl EncryptHelper { pub async fn new(context: &Context) -> Result { - let prefer_encrypt = - EncryptPreference::from_i32(context.get_config_int(Config::E2eeEnabled).await?) - .unwrap_or_default(); + let prefer_encrypt = EncryptPreference::Mutual; let addr = context.get_primary_self_addr().await?; let public_key = load_self_public_key(context).await?; diff --git a/src/imex.rs b/src/imex.rs index 3ccdc4615..56f018acb 100644 --- a/src/imex.rs +++ b/src/imex.rs @@ -140,32 +140,8 @@ pub async fn has_backup(_context: &Context, dir_name: &Path) -> Result { } async fn set_self_key(context: &Context, armored: &str) -> Result<()> { - // try hard to only modify key-state - let (private_key, header) = SignedSecretKey::from_asc(armored)?; + let private_key = SignedSecretKey::from_asc(armored)?; let public_key = private_key.split_public_key()?; - if let Some(preferencrypt) = header.get("Autocrypt-Prefer-Encrypt") { - let e2ee_enabled = match preferencrypt.as_str() { - "nopreference" => 0, - "mutual" => 1, - _ => { - bail!("invalid Autocrypt-Prefer-Encrypt header: {:?}", header); - } - }; - context - .sql - .set_raw_config_int("e2ee_enabled", e2ee_enabled) - .await?; - } else { - // `Autocrypt-Prefer-Encrypt` is not included - // in keys exported to file. - // - // `Autocrypt-Prefer-Encrypt` also SHOULD be sent - // in Autocrypt Setup Message according to Autocrypt specification, - // but K-9 6.802 does not include this header. - // - // We keep current setting in this case. - info!(context, "No Autocrypt-Prefer-Encrypt header."); - }; let keypair = pgp::KeyPair { public: public_key, diff --git a/src/imex/key_transfer.rs b/src/imex/key_transfer.rs index 2df464391..6d1f9f418 100644 --- a/src/imex/key_transfer.rs +++ b/src/imex/key_transfer.rs @@ -93,10 +93,7 @@ pub async fn render_setup_file(context: &Context, passphrase: &str) -> Result None, - true => Some(("Autocrypt-Prefer-Encrypt", "mutual")), - }; + let ac_headers = Some(("Autocrypt-Prefer-Encrypt", "mutual")); let private_key_asc = private_key.to_asc(ac_headers); let encr = pgp::symm_encrypt(passphrase, private_key_asc.into_bytes()) .await? diff --git a/src/key.rs b/src/key.rs index 7d01812d2..e9ca6c595 100644 --- a/src/key.rs +++ b/src/key.rs @@ -71,31 +71,17 @@ pub(crate) trait DcKey: Serialize + Deserializable + Clone { } /// Create a key from an ASCII-armored string. - /// - /// Returns the key and a map of any headers which might have been set in - /// the ASCII-armored representation. - fn from_asc(data: &str) -> Result<(Self, BTreeMap)> { + fn from_asc(data: &str) -> Result { let bytes = data.as_bytes(); let res = Self::from_armor_single(Cursor::new(bytes)); - let (key, headers) = match res { + let (key, _headers) = match res { Err(pgp::errors::Error::NoMatchingPacket { .. }) => match Self::is_private() { true => bail!("No private key packet found"), false => bail!("No public key packet found"), }, _ => res.context("rPGP error")?, }; - let headers = headers - .into_iter() - .map(|(key, values)| { - ( - key.trim().to_lowercase(), - values - .last() - .map_or_else(String::new, |s| s.trim().to_string()), - ) - }) - .collect(); - Ok((key, headers)) + Ok(key) } /// Serialise the key as bytes. @@ -446,7 +432,7 @@ pub(crate) async fn store_self_keypair(context: &Context, keypair: &KeyPair) -> /// to avoid generating the key in tests. /// Use import/export APIs instead. pub async fn preconfigure_keypair(context: &Context, secret_data: &str) -> Result<()> { - let secret = SignedSecretKey::from_asc(secret_data)?.0; + let secret = SignedSecretKey::from_asc(secret_data)?; let public = secret.split_public_key()?; let keypair = KeyPair { public, secret }; store_self_keypair(context, &keypair).await?; @@ -532,7 +518,7 @@ mod tests { #[test] fn test_from_armored_string() { - let (private_key, _) = SignedSecretKey::from_asc( + let private_key = SignedSecretKey::from_asc( "-----BEGIN PGP PRIVATE KEY BLOCK----- xcLYBF0fgz4BCADnRUV52V4xhSsU56ZaAn3+3oG86MZhXy4X8w14WZZDf0VJGeTh @@ -600,17 +586,13 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD fn test_asc_roundtrip() { let key = KEYPAIR.public.clone(); let asc = key.to_asc(Some(("spam", "ham"))); - let (key2, hdrs) = SignedPublicKey::from_asc(&asc).unwrap(); + let key2 = SignedPublicKey::from_asc(&asc).unwrap(); assert_eq!(key, key2); - assert_eq!(hdrs.len(), 1); - assert_eq!(hdrs.get("spam"), Some(&String::from("ham"))); let key = KEYPAIR.secret.clone(); let asc = key.to_asc(Some(("spam", "ham"))); - let (key2, hdrs) = SignedSecretKey::from_asc(&asc).unwrap(); + let key2 = SignedSecretKey::from_asc(&asc).unwrap(); assert_eq!(key, key2); - assert_eq!(hdrs.len(), 1); - assert_eq!(hdrs.get("spam"), Some(&String::from("ham"))); } #[test] diff --git a/src/mimeparser.rs b/src/mimeparser.rs index e42647680..467a82b33 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -1519,7 +1519,7 @@ impl MimeMessage { ); return Ok(false); } - Ok((key, _)) => key, + Ok(key) => key, }; if let Err(err) = key.verify() { warn!(context, "Attached PGP key verification failed: {err:#}."); diff --git a/src/push.rs b/src/push.rs index ffd31cd9c..8b4bcc3ca 100644 --- a/src/push.rs +++ b/src/push.rs @@ -74,7 +74,7 @@ fn pad_device_token(s: &str) -> String { /// /// The result is base64-encoded and not ASCII armored to avoid dealing with newlines. pub(crate) fn encrypt_device_token(device_token: &str) -> Result { - let public_key = pgp::composed::SignedPublicKey::from_asc(NOTIFIERS_PUBLIC_KEY)?.0; + let public_key = pgp::composed::SignedPublicKey::from_asc(NOTIFIERS_PUBLIC_KEY)?; let encryption_subkey = public_key .public_subkeys .first() diff --git a/src/test_utils.rs b/src/test_utils.rs index 0534a66fc..083f0b5c5 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -1245,9 +1245,8 @@ impl SentMessage<'_> { /// /// The keypair was created using the crate::key::tests::gen_key test. pub fn alice_keypair() -> KeyPair { - let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/alice-secret.asc")) - .unwrap() - .0; + let secret = + key::SignedSecretKey::from_asc(include_str!("../test-data/key/alice-secret.asc")).unwrap(); let public = secret.split_public_key().unwrap(); KeyPair { public, secret } } @@ -1256,9 +1255,8 @@ pub fn alice_keypair() -> KeyPair { /// /// Like [alice_keypair] but a different key and identity. pub fn bob_keypair() -> KeyPair { - let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/bob-secret.asc")) - .unwrap() - .0; + let secret = + key::SignedSecretKey::from_asc(include_str!("../test-data/key/bob-secret.asc")).unwrap(); let public = secret.split_public_key().unwrap(); KeyPair { public, secret } } @@ -1269,8 +1267,7 @@ pub fn bob_keypair() -> KeyPair { pub fn charlie_keypair() -> KeyPair { let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/charlie-secret.asc")) - .unwrap() - .0; + .unwrap(); let public = secret.split_public_key().unwrap(); KeyPair { public, secret } } @@ -1279,9 +1276,8 @@ pub fn charlie_keypair() -> KeyPair { /// /// Like [alice_keypair] but a different key and identity. pub fn dom_keypair() -> KeyPair { - let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/dom-secret.asc")) - .unwrap() - .0; + let secret = + key::SignedSecretKey::from_asc(include_str!("../test-data/key/dom-secret.asc")).unwrap(); let public = secret.split_public_key().unwrap(); KeyPair { public, secret } } @@ -1290,9 +1286,8 @@ pub fn dom_keypair() -> KeyPair { /// /// Like [alice_keypair] but a different key and identity. pub fn elena_keypair() -> KeyPair { - let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/elena-secret.asc")) - .unwrap() - .0; + let secret = + key::SignedSecretKey::from_asc(include_str!("../test-data/key/elena-secret.asc")).unwrap(); let public = secret.split_public_key().unwrap(); KeyPair { public, secret } } @@ -1301,9 +1296,8 @@ pub fn elena_keypair() -> KeyPair { /// /// Like [alice_keypair] but a different key and identity. pub fn fiona_keypair() -> KeyPair { - let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/fiona-secret.asc")) - .unwrap() - .0; + let secret = + key::SignedSecretKey::from_asc(include_str!("../test-data/key/fiona-secret.asc")).unwrap(); let public = secret.split_public_key().unwrap(); KeyPair { public, secret } }