From 09d5d0bddff52f38134a0638d8304d777285b66f Mon Sep 17 00:00:00 2001 From: link2xt Date: Wed, 24 Jun 2026 02:42:51 +0000 Subject: [PATCH] chore: update rPGP from 0.19.0 to 0.20.0 --- Cargo.lock | 52 +++++++++++++++++++++++++++++++++++--------------- Cargo.toml | 2 +- deny.toml | 2 ++ src/decrypt.rs | 36 +++++++++++++++++++++++++++------- src/pgp.rs | 17 ++++++----------- 5 files changed, 75 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e650c8ca9..9d140fb54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1710,7 +1710,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.1", ] [[package]] @@ -2733,7 +2733,7 @@ dependencies = [ "hyper", "libc", "pin-project-lite", - "socket2 0.5.9", + "socket2 0.6.3", "tokio", "tower-service", "tracing", @@ -3154,7 +3154,7 @@ dependencies = [ "iroh-metrics-derive", "itoa", "serde", - "snafu", + "snafu 0.8.5", "tracing", ] @@ -3524,9 +3524,9 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.7.4" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "mime" @@ -3792,7 +3792,7 @@ dependencies = [ "netlink-proto", "netlink-sys", "serde", - "snafu", + "snafu 0.8.5", "socket2 0.5.9", "time", "tokio", @@ -3880,7 +3880,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.1", ] [[package]] @@ -4284,9 +4284,9 @@ dependencies = [ [[package]] name = "pgp" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaffe1ec22db286599c30ae6be75b37493b558735d86c8e59ec5c38794415fe4" +checksum = "1cfa4743b28656065ff4c0ba09e46b357a65e8c00fc2341e89084b82f87cbdf1" dependencies = [ "aead", "aes", @@ -4325,6 +4325,7 @@ dependencies = [ "k256", "log", "md-5", + "memchr", "ml-dsa", "ml-kem", "nom 8.0.0", @@ -4336,7 +4337,6 @@ dependencies = [ "p384", "p521", "rand 0.8.6", - "regex", "replace_with", "ripemd", "rsa", @@ -4347,7 +4347,8 @@ dependencies = [ "signature", "slh-dsa", "smallvec", - "snafu", + "snafu 0.9.1", + "subtle", "twofish", "x25519-dalek", "zeroize", @@ -4586,7 +4587,7 @@ dependencies = [ "rand 0.8.6", "serde", "smallvec", - "snafu", + "snafu 0.8.5", "socket2 0.5.9", "time", "tokio", @@ -5281,7 +5282,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.52.0", + "windows-sys 0.61.1", ] [[package]] @@ -5849,7 +5850,16 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019" dependencies = [ - "snafu-derive", + "snafu-derive 0.8.5", +] + +[[package]] +name = "snafu" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1a012328be2e3f5d5f6f3218147ca02588cea4cb865e876849ab6debcf36522" +dependencies = [ + "snafu-derive 0.9.1", ] [[package]] @@ -5864,6 +5874,18 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "snafu-derive" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f103c50866b8743da9429b8a581d81a27c2d3a9c4ac7df8f8571c1dd7896eda" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "socket2" version = "0.5.9" @@ -6147,7 +6169,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix 1.1.4", - "windows-sys 0.52.0", + "windows-sys 0.61.1", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ed2050334..238f7a8f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,7 +78,7 @@ num-derive = "0.4" num-traits = { workspace = true } parking_lot = "0.12.4" percent-encoding = "2.3" -pgp = { version = "0.19.0", features = ["draft-pqc"], default-features = false } +pgp = { version = "0.20.0", features = ["draft-pqc"], default-features = false } pin-project = "1" qrcodegen = "1.7.0" quick-xml = { version = "0.39", features = ["escape-html"] } diff --git a/deny.toml b/deny.toml index b32af0979..45e7bae71 100644 --- a/deny.toml +++ b/deny.toml @@ -83,6 +83,8 @@ skip = [ { name = "rustix", version = "0.38.44" }, { name = "rustls-webpki", version = "0.102.8" }, { name = "serdect", version = "0.2.0" }, + { name = "snafu-derive", version = "0.8.5" }, + { name = "snafu", version = "0.8.5" }, { name = "socket2", version = "0.5.9" }, { name = "spin", version = "0.9.8" }, { name = "strum_macros", version = "0.26.2" }, diff --git a/src/decrypt.rs b/src/decrypt.rs index 5768aff4a..eb335614d 100644 --- a/src/decrypt.rs +++ b/src/decrypt.rs @@ -6,13 +6,16 @@ use std::io::Cursor; use anyhow::{Context as _, Result, bail}; use mailparse::ParsedMail; +use pgp::composed::DecryptionOptions; use pgp::composed::Esk; use pgp::composed::Message; use pgp::composed::PlainSessionKey; use pgp::composed::SignedSecretKey; +use pgp::composed::TheRing; use pgp::composed::decrypt_session_key_with_password; use pgp::packet::SymKeyEncryptedSessionKey; use pgp::types::Password; +use pgp::types::Seipdv1ReadMode; use pgp::types::StringToKey; use crate::chat::ChatId; @@ -48,6 +51,15 @@ pub(crate) async fn decrypt( }; let expected_sender_fingerprint: Option; + let abort_early = true; + + // Use streaming mode for SEIPDv1 decryption to save memory. + // This was the default in rPGP 0.19.0 + // and requires explicitly changing the mode in rPGP 0.20.0. + // SEPIDv2 is decrypted in streaming mode in any case. + let decrypt_options = + DecryptionOptions::new().set_seipdv1_read_mode(Seipdv1ReadMode::Streaming); + let plain = if let Message::Encrypted { esk, .. } = &*msg // We only allow one ESK for symmetrically encrypted messages // to avoid dealing with messages that are encrypted to multiple symmetric keys @@ -61,9 +73,15 @@ pub(crate) async fn decrypt( expected_sender_fingerprint = fingerprint; tokio::task::spawn_blocking(move || -> Result> { - let plain = msg - .decrypt_with_session_key(psk) - .context("decrypt_with_session_key")?; + let ring = TheRing { + session_keys: vec![psk], + decrypt_options, + ..Default::default() + }; + + let (plain, _ring_result) = msg + .decrypt_the_ring(ring, abort_early) + .context("decrypt_the_ring")?; let plain: Message<'static> = plain.decompress()?; Ok(plain) @@ -75,11 +93,15 @@ pub(crate) async fn decrypt( expected_sender_fingerprint = None; tokio::task::spawn_blocking(move || -> Result> { - let empty_pw = Password::empty(); let secret_keys: Vec<&SignedSecretKey> = secret_keys.iter().collect(); - let plain = msg - .decrypt_with_keys(vec![&empty_pw], secret_keys) - .context("decrypt_with_keys")?; + let ring = TheRing { + secret_keys, + decrypt_options, + ..Default::default() + }; + let (plain, _ring_result) = msg + .decrypt_the_ring(ring, abort_early) + .context("decrypt_the_ring")?; let plain: Message<'static> = plain.decompress()?; Ok(plain) diff --git a/src/pgp.rs b/src/pgp.rs index f573e5468..8821d3610 100644 --- a/src/pgp.rs +++ b/src/pgp.rs @@ -34,7 +34,7 @@ const SYMMETRIC_KEY_ALGORITHM: SymmetricKeyAlgorithm = SymmetricKeyAlgorithm::AE /// as [described in the Autocrypt standard](https://autocrypt.org/level1.html#openpgp-based-key-data). pub(crate) fn create_keypair(addr: EmailAddress) -> Result { let signing_key_type = PgpKeyType::Ed25519Legacy; - let encryption_key_type = PgpKeyType::ECDH(ECCCurve::Curve25519); + let encryption_key_type = PgpKeyType::ECDH(ECCCurve::Curve25519Legacy); let user_id = format!("<{addr}>"); let key_params = SecretKeyParamsBuilder::default() @@ -371,10 +371,7 @@ pub fn merge_openpgp_certificates( .into_iter() .chain(new_direct_signatures) .filter(|x: &Signature| x.verify_key(&old_primary_key).is_ok()) - .max_by_key(|x: &Signature| - // Converting to seconds because `Ord` is not derived for `Timestamp`: - // - x.created().map_or(0, |ts| ts.as_secs())); + .max_by_key(|x: &Signature| x.created()); let direct_signatures: Vec = best_direct_key_signature.into_iter().collect(); // Select at most one User ID. @@ -396,12 +393,10 @@ pub fn merge_openpgp_certificates( .verify_certification(&old_primary_key, pgp::types::Tag::UserId, &id) .is_ok() }) - .max_by_key(|signature: &Signature| { - signature.created().map_or(0, |ts| ts.as_secs()) - }); + .max_by_key(|signature: &Signature| signature.created()); best_user_signature.map(|signature| (id, signature)) }) - .max_by_key(|(_id, signature)| signature.created().map_or(0, |ts| ts.as_secs())) + .max_by_key(|(_id, signature)| signature.created()) .map(|(id, signature)| SignedUser { id, signatures: vec![signature], @@ -707,7 +702,7 @@ mod tests { // This error message is actually not great, // but grepping for it will lead to the correct code - test_dont_decrypt_expensive_message_ex(s2k, true, Some("decrypt_with_keys: missing key")) + test_dont_decrypt_expensive_message_ex(s2k, true, Some("decrypt_the_ring: missing key")) .await } @@ -790,7 +785,7 @@ mod tests { .await .unwrap_err(); - assert_eq!(format!("{error:#}"), "decrypt_with_keys: missing key"); + assert_eq!(format!("{error:#}"), "decrypt_the_ring: missing key"); Ok(()) }