From c543bc8f14752551733c1970302e5a06f1a9d2ac Mon Sep 17 00:00:00 2001 From: link2xt Date: Sat, 16 Aug 2025 23:33:38 +0000 Subject: [PATCH] refactor(mimeparser): store only one signature fingerprint Messages are normally not signed with more than one key and in this case we pick an arbitrary signature later anyway. --- src/mimeparser.rs | 10 +++++----- src/receive_imf.rs | 7 +++++-- src/securejoin.rs | 20 +++++++++++--------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/mimeparser.rs b/src/mimeparser.rs index b84235180c..3943bea08e 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -87,12 +87,12 @@ pub(crate) struct MimeMessage { pub chat_disposition_notification_to: Option, pub decrypting_failed: bool, - /// Set of valid signature fingerprints if a message is an + /// Valid signature fingerprint if a message is an /// Autocrypt encrypted and signed message. /// /// If a message is not encrypted or the signature is not valid, - /// this set is empty. - pub signatures: HashSet, + /// this is `None`. + pub signature: Option, /// The addresses for which there was a gossip header /// and their respective gossiped keys. @@ -589,7 +589,7 @@ impl MimeMessage { decrypting_failed: mail.is_err(), // only non-empty if it was a valid autocrypt message - signatures, + signature: signatures.into_iter().last(), autocrypt_fingerprint, gossiped_keys, is_forwarded: false, @@ -966,7 +966,7 @@ impl MimeMessage { /// This means the message was both encrypted and signed with a /// valid signature. pub fn was_encrypted(&self) -> bool { - !self.signatures.is_empty() + self.signature.is_some() } /// Returns whether the email contains a `chat-version` header. diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 47903206c1..fd192e1462 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -642,7 +642,7 @@ pub(crate) async fn receive_imf_inner( // For example, GitHub sends messages from `notifications@github.com`, // but uses display name of the user whose action generated the notification // as the display name. - let fingerprint = mime_parser.signatures.iter().next(); + let fingerprint = mime_parser.signature.as_ref(); let (from_id, _from_id_blocked, incoming_origin) = match from_field_to_contact_id( context, &mime_parser.from, @@ -3662,7 +3662,10 @@ async fn has_verified_encryption( )); } - let signed_with_verified_key = mimeparser.signatures.contains(&fingerprint); + let signed_with_verified_key = mimeparser + .signature + .as_ref() + .is_some_and(|signature| *signature == fingerprint); if signed_with_verified_key { Ok(Verified) } else { diff --git a/src/securejoin.rs b/src/securejoin.rs index 04642ac945..daaff1eb78 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -623,17 +623,19 @@ fn encrypted_and_signed( mimeparser: &MimeMessage, expected_fingerprint: &Fingerprint, ) -> bool { - if !mimeparser.was_encrypted() { + if let Some(signature) = mimeparser.signature.as_ref() { + if signature == expected_fingerprint { + true + } else { + warn!( + context, + "Message does not match expected fingerprint {expected_fingerprint}.", + ); + false + } + } else { warn!(context, "Message not encrypted.",); false - } else if !mimeparser.signatures.contains(expected_fingerprint) { - warn!( - context, - "Message does not match expected fingerprint {}.", expected_fingerprint, - ); - false - } else { - true } }