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<'_>,
)
| 39 | /// If Alice sends an answer (or read receipt), |
| 40 | /// then Eve would know that Alice is in the broadcast channel. |
| 41 | pub(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 | |
| 93 | async fn decrypt_session_key_symmetrically( |
| 94 | context: &Context, |
no test coverage detected