feat: assign messages to key-contacts based on Issuer Fingerprint

This commit is contained in:
link2xt
2025-08-14 20:33:58 +00:00
committed by l
parent ac10103b18
commit a89b6321f1
3 changed files with 116 additions and 1 deletions

View File

@@ -427,7 +427,7 @@ impl MimeMessage {
None
};
let public_keyring = if incoming {
let mut public_keyring = if incoming {
if let Some(autocrypt_header) = autocrypt_header {
vec![autocrypt_header.public_key]
} else {
@@ -437,6 +437,44 @@ impl MimeMessage {
key::load_self_public_keyring(context).await?
};
if let Some(signature) = match &decrypted_msg {
Some(pgp::composed::Message::Literal { .. }) => None,
Some(pgp::composed::Message::Compressed { .. }) => {
// One layer of compression should already be handled by now.
// We don't decompress messages compressed multiple times.
None
}
Some(pgp::composed::Message::SignedOnePass { reader, .. }) => reader.signature(),
Some(pgp::composed::Message::Signed { reader, .. }) => Some(reader.signature()),
Some(pgp::composed::Message::Encrypted { .. }) => {
// The message is already decrypted once.
None
}
None => None,
} {
for issuer_fingerprint in signature.issuer_fingerprint() {
let issuer_fingerprint =
crate::key::Fingerprint::from(issuer_fingerprint.clone()).hex();
if let Some(public_key_bytes) = context
.sql
.query_row_optional(
"SELECT public_key
FROM public_keys
WHERE fingerprint=?",
(&issuer_fingerprint,),
|row| {
let bytes: Vec<u8> = row.get(0)?;
Ok(bytes)
},
)
.await?
{
let public_key = SignedPublicKey::from_slice(&public_key_bytes)?;
public_keyring.push(public_key)
}
}
}
let mut signatures = if let Some(ref decrypted_msg) = decrypted_msg {
crate::pgp::valid_signature_fingerprints(decrypted_msg, &public_keyring)?
} else {

View File

@@ -3316,6 +3316,31 @@ async fn test_thunderbird_autocrypt() -> Result<()> {
Ok(())
}
/// Tests that a message without an Autocrypt header is assigned to the key-contact
/// by using the signature Issuer Fingerprint.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_issuer_fingerprint() -> Result<()> {
let mut tcm = TestContextManager::new();
let alice = &tcm.alice().await;
let bob = &tcm.bob().await;
let alice_contact_id = bob.add_or_lookup_contact_id(alice).await;
let raw = include_bytes!("../../test-data/message/encrypted-signed.eml");
let received_msg = receive_imf(bob, raw, false).await?.unwrap();
assert_eq!(received_msg.msg_ids.len(), 1);
let msg_id = received_msg.msg_ids[0];
let message = Message::load_from_db(bob, msg_id).await?;
assert!(message.get_showpadlock());
let from_id = message.from_id;
assert_eq!(from_id, alice_contact_id);
Ok(())
}
/// Tests reception of a message from Thunderbird with attached key.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_prefer_encrypt_mutual_if_encrypted() -> Result<()> {