Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to OpenPGP RFC 9580 / Sequoia 2.0 #7225

Open
legoktm opened this issue Aug 26, 2024 · 2 comments
Open

Update to OpenPGP RFC 9580 / Sequoia 2.0 #7225

legoktm opened this issue Aug 26, 2024 · 2 comments
Labels

Comments

@legoktm
Copy link
Member

legoktm commented Aug 26, 2024

Description

OpenPGP has a new RFC dubbed "crypto refresh" that updates a lot of things to modern practices, there's a good summary at https://proton.me/blog/openpgp-crypto-refresh

Neal of Sequoia said that they'll be releasing 2.0 at the end of the year, which will include support for it. They also provided a link to https://www.openpgp.org/community/email-summit/2024/minutes/#mechanism-of-key-migration which discusses what migrations might look like.

Roughly as I understand it:

  • Newsrooms will need to generate a V6 secret key and provision the public key and cross-sign them somehow(?)
  • New sources will get V6 key pairs, older sources will have V4 keys and we can generate V6 for them on login for future messages, but we need to retain the V4 key to decrypt older messages.

The elephant in the room is that we're still using GPG in places like the SecureDrop Workstation (freedomofpress/securedrop-workstation#812) and Tails Workstation (no issue). Because of the schism, it seems likely that we need to fully leave GPG behind and embrace Sequoia/other OpenPGP-based tools.

@legoktm legoktm added the gpg label Aug 26, 2024
@legoktm
Copy link
Member Author

legoktm commented Aug 26, 2024

Neal of Sequoia said that they'll be releasing 2.0 at the end of the year

Forgot to mention that https://gitlab.com/sequoia-pgp/sequoia/-/tree/crypto-refresh exists, it was a small diff to get code to compile:

diff --git a/redwood/Cargo.toml b/redwood/Cargo.toml
index 33f77aeff..a53f69d36 100644
--- a/redwood/Cargo.toml
+++ b/redwood/Cargo.toml
@@ -11,7 +11,7 @@ crate-type = ["cdylib"]
 [dependencies]
 anyhow = "1.0"
 pyo3 = { version = "0.18.0", features = ["extension-module"] }
-sequoia-openpgp = { version = "1.21.1", default-features = false, features = ["crypto-openssl", "compression"]}
+sequoia-openpgp = { git = "https://gitlab.com/sequoia-pgp/sequoia/", branch = "crypto-refresh", default-features = false, features = ["crypto-openssl", "compression"]}
 thiserror = "1.0.31"
 
 [dev-dependencies]
diff --git a/redwood/src/decryption.rs b/redwood/src/decryption.rs
index 8175063e3..bfdbc165b 100644
--- a/redwood/src/decryption.rs
+++ b/redwood/src/decryption.rs
@@ -41,26 +41,28 @@ impl<'a> DecryptionHelper for Helper<'a> {
         mut decrypt: D,
     ) -> sequoia_openpgp::Result<Option<sequoia_openpgp::Fingerprint>>
     where
-        D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool,
+        D: FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool,
     {
         let key = secret_key_from_cert(self.secret)?;
 
         for pkesk in pkesks {
             // Note: this check won't work for messages encrypted with --throw-keyids,
             // but we don't generate any messages that use it.
-            if pkesk.recipient() == &key.keyid() {
-                // Decrypt the secret key with the specified passphrase.
-                let mut pair = key
-                    .clone()
-                    .decrypt_secret(self.passphrase)?
-                    .into_keypair()?;
-                pkesk
-                    .decrypt(&mut pair, sym_algo)
-                    .map(|(algo, session_key)| decrypt(algo, &session_key));
-                // Return the fingerprint of the key we decrypted with, this is used in
-                // conjunction with the intended recipient subpacket (see "Intended Recipient Fingerprint"
-                // in RFC 4880bis) to prevent Surreptitious Forwarding.
-                return Ok(Some(key.fingerprint()));
+            if let Some(recipient) = pkesk.recipient() {
+                if recipient == key.key_handle() {
+                    // Decrypt the secret key with the specified passphrase.
+                    let mut pair = key
+                        .clone()
+                        .decrypt_secret(self.passphrase)?
+                        .into_keypair()?;
+                    pkesk
+                        .decrypt(&mut pair, sym_algo)
+                        .map(|(algo, session_key)| decrypt(algo, &session_key));
+                    // Return the fingerprint of the key we decrypted with, this is used in
+                    // conjunction with the intended recipient subpacket (see "Intended Recipient Fingerprint"
+                    // in RFC 4880bis) to prevent Surreptitious Forwarding.
+                    return Ok(Some(key.fingerprint()));
+                }
             }
         }

Tests don't pass yet (maybe I mis-ported the key handle stuff):

test tests::test_multiple_recipients ... FAILED

---- tests::test_multiple_recipients stdout ----
/tmp/.tmpZauY30/message.asc
thread 'tests::test_multiple_recipients' panicked at redwood/src/lib.rs:376:18:
called `Result::unwrap()` on an `Err` value: OpenPgp(no matching pkesk, wrong secret key provided?)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I don't think we need to do anything on this now, we can pick this up once Sequoia 2.0 is closer.

@cfm
Copy link
Member

cfm commented Aug 29, 2024

  • New sources will get V6 key pairs, older sources will have V4 keys and we can generate V6 for them on login for future messages, but we need to retain the V4 key to decrypt older messages.

The elephant in the room is that we're still using GPG in places like the SecureDrop Workstation (freedomofpress/securedrop-workstation#812) and Tails Workstation (no issue). Because of the schism, it seems likely that we need to fully leave GPG behind and embrace Sequoia/other OpenPGP-based tools.

I think this is right. We should also try to make https://github.com/freedomofpress/securedrop-workstation-docs/blob/8734793c1d024c779c2ee65b26c64045db5c0e03/docs/general/known_issues.rst?plain=1#L48-L50 not true: i.e., support a set of keys both at Workstation provisioning and Client runtime.

legoktm added a commit that referenced this issue Sep 19, 2024
Upgrade ruff to the latest version so we can use it for formatting and
native editor integration. While we're at it, introduce the standard
`make fix` target
(<freedomofpress/securedrop-tooling#11>).

Actually fixing new issues will happen in follow-ups to make this change
easier to review.

Fixes #7225.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants
@legoktm @cfm and others