mirror of
https://github.com/chatmail/core.git
synced 2026-04-27 18:36:30 +03:00
feat: assign messages to key-contacts based on Issuer Fingerprint
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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<()> {
|
||||
|
||||
52
test-data/message/encrypted-signed.eml
Normal file
52
test-data/message/encrypted-signed.eml
Normal file
@@ -0,0 +1,52 @@
|
||||
Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";
|
||||
boundary="18566fe03178296e_f40510c3b59ace3_ecf843ae3ccd2b17"
|
||||
MIME-Version: 1.0
|
||||
From: alice@example.org
|
||||
To: bob@example.net
|
||||
Subject: [...]
|
||||
Date: Mon, 28 Jul 2025 14:15:14 +0000
|
||||
Message-ID: <48b9e9cc-2bae-4d41-89b4-a409e2c60c28@localhost>
|
||||
References: <48b9e9cc-2bae-4d41-89b4-a409e2c60c28@localhost>
|
||||
Chat-Version: 1.0
|
||||
|
||||
|
||||
--18566fe03178296e_f40510c3b59ace3_ecf843ae3ccd2b17
|
||||
Content-Type: application/pgp-encrypted; charset="utf-8"
|
||||
Content-Description: PGP/MIME version identification
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
Version: 1
|
||||
|
||||
--18566fe03178296e_f40510c3b59ace3_ecf843ae3ccd2b17
|
||||
Content-Type: application/octet-stream; name="encrypted.asc";
|
||||
charset="utf-8"
|
||||
Content-Description: OpenPGP encrypted message
|
||||
Content-Disposition: inline; filename="encrypted.asc";
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
|
||||
wV4D5tq63hTeebASAQdAaI0Cw7tTd10Oz0I1C1Ds5NpF/m6zXlx73Pxzib6Q2Qow
|
||||
36Fc9KiSZx+vXlw9mZ9zYpumIY/svkYcTRdZwohPWe4TL7iRC8gTZ43/VGZvb+1k
|
||||
wcBMA+PY3JvEjuMiAQf+MCZLm1vgocYO0xRz2J9Z9QGqScfxBMhYToZbFTx4DAha
|
||||
hejVmW9AGnNqm8yky2DJpqT3oy//D261HX+xzLfkfWFgHzKud7NtMN6II/d1jyqO
|
||||
A+K0LjSLPcR3aWl8g30+6bGhHCwc2spP3gIk1aE8S/1c/yQPxD7mqNSkYrY6BgHP
|
||||
+5Z7ocrud4RKVQayZsWpiiY962w1GJii1h4zE+xhkqFERr1OqepQB7CDf4FBsGr0
|
||||
qarJtcWCGqd9ksr/wn8Ew9MPHz+8ooCSlXzJ7Uac4VshUm9dXzO3NSS6MgTME0av
|
||||
WRlRiKuGCmrS4dyf/Tdj1yMB3jJ52SxdEq0yYYLKvdLBWAF9JU7sQp3x4oivpr5U
|
||||
wv5OP/tbfRVA2zqkOHlMhBAXaLOsiJrHYh3ieJLwfWSmEQARLE7sBgD5fqre1v+D
|
||||
Xpof8R42j9MQ3St/+nPDsLpbZ2a2RKBl16C8IYnmK1CYwh5lEK533HMHeSLka/ng
|
||||
soK2HqJxrhkxYpm5OPWN8liSdKlQ8mZXISGNPo8KEWFlPqONqj88UudpQiPCh2qw
|
||||
aeFC2Y1EkQQGpiTq1GuTQfG8zO4wa3FTW1wOELsvYozszS1Oc1exH767pS+ozNWa
|
||||
xk8J7ekEFvR5b3TUK2a/ucmRgXuuowCxxV6EiNeRqGa3SfQnQWnMkqsVIeIiARDt
|
||||
QMbRCrrAjJ+dQEekviq/hqq9+DRLuX0hOybe8aYjJttg7NLgaM04V4QuvWeVQa2g
|
||||
2IBR2Nw1pcvbyDRkTLsQ2AlR/ig5VPf+4oqN2nBuXgPzply9LU5JyhW9GNIhH+N1
|
||||
K6w8o5o4ebUx0ldaTjBnrFMUqih4nE9qrrb0UYMcQO3HVAueQii0CZqhJy/n/6U6
|
||||
cAhnh/fTI1wMoYuYR7cLdf+9P7dHcQPdt3FQA/NrRpv31tyzzKNeBr0VdvoT0uwX
|
||||
sv0nh+ACjnum7H8yCyoe1tIqUPW0byslROuHAfMwp7rsnBEGJ4AqFYNIdpfSFuia
|
||||
LsZmODaUG1n6XkamfKPin+Z5Mo8/bK0KwE317Zc/aQD/okvGv4SWsQmW
|
||||
=hj9/
|
||||
-----END PGP MESSAGE-----
|
||||
|
||||
|
||||
--18566fe03178296e_f40510c3b59ace3_ecf843ae3ccd2b17--
|
||||
Reference in New Issue
Block a user