MCPcopy Create free account
hub / github.com/chatmail/core / decrypt

Function decrypt

src/decrypt.rs:41–91  ·  view source on GitHub ↗

Tries to decrypt the message, returning a tuple of `(decrypted message, fingerprint)`. If the message wasn't encrypted, returns `Ok(None)`. If the message was asymmetrically encrypted, returns `Ok((decrypted message, None))`. If the message was symmetrically encrypted, returns `Ok((decrypted message, Some(fingerprint)))`, where `fingerprint` denotes which contact is allowed to send encrypted wi

(
    context: &Context,
    mail: &mailparse::ParsedMail<'_>,
)

Source from the content-addressed store, hash-verified

39/// If Alice sends an answer (or read receipt),
40/// then Eve would know that Alice is in the broadcast channel.
41pub(crate) async fn decrypt(
42 context: &Context,
43 mail: &mailparse::ParsedMail<'_>,
44) -> Result<Option<(Message<'static>, Option<String>)>> {
45 // `pgp::composed::Message` is huge (>4kb), so, make sure that it is in a Box when held over an await point
46 let Some(msg) = get_encrypted_pgp_message_boxed(mail)? else {
47 return Ok(None);
48 };
49 let expected_sender_fingerprint: Option<String>;
50
51 let plain = if let Message::Encrypted { esk, .. } = &*msg
52 // We only allow one ESK for symmetrically encrypted messages
53 // to avoid dealing with messages that are encrypted to multiple symmetric keys
54 // or a mix of symmetric and asymmetric keys:
55 && let [Esk::SymKeyEncryptedSessionKey(esk)] = &esk[..]
56 {
57 check_symmetric_encryption(esk)?;
58 let (psk, fingerprint) = decrypt_session_key_symmetrically(context, esk)
59 .await
60 .context("decrypt_session_key_symmetrically")?;
61 expected_sender_fingerprint = fingerprint;
62
63 tokio::task::spawn_blocking(move || -> Result<Message<'_>> {
64 let plain = msg
65 .decrypt_with_session_key(psk)
66 .context("decrypt_with_session_key")?;
67
68 let plain: Message<'static> = plain.decompress()?;
69 Ok(plain)
70 })
71 .await??
72 } else {
73 // Message is asymmetrically encrypted
74 let secret_keys: Vec<SignedSecretKey> = load_self_secret_keyring(context).await?;
75 expected_sender_fingerprint = None;
76
77 tokio::task::spawn_blocking(move || -> Result<Message<'_>> {
78 let empty_pw = Password::empty();
79 let secret_keys: Vec<&SignedSecretKey> = secret_keys.iter().collect();
80 let plain = msg
81 .decrypt_with_keys(vec![&empty_pw], secret_keys)
82 .context("decrypt_with_keys")?;
83
84 let plain: Message<'static> = plain.decompress()?;
85 Ok(plain)
86 })
87 .await??
88 };
89
90 Ok(Some((plain, expected_sender_fingerprint)))
91}
92
93async fn decrypt_session_key_symmetrically(
94 context: &Context,

Callers 2

decrypt_bytesFunction · 0.85
from_bytesMethod · 0.85

Calls 5

load_self_secret_keyringFunction · 0.85
iterMethod · 0.45

Tested by

no test coverage detected