Hi all,
SecureDrop is migrating from GPG to Sequoia in our upcoming 2.7.0 release. I want to give a brief overview of how SecureDrop works and then a request for review if anyone has some time.
For those not familiar, SecureDrop is a whistleblower submission system. Sources upload documents and send messages for journalists to review said information and determine whether or not to act on it. There's a high-level architecture overview at https://docs.securedrop.org/en/stable/what_is_securedrop.html.
== Our PGP operations ==
Submissions are encrypted for journalists using PGP. The journalist secret key is kept offline on an airgapped machine, while the public key is on the SecureDrop server and generally publicly available.
When a source logs in, they are given a diceware passphrase ("codename" in SD documentation). The server generates a PGP keypair protected by that passphrase. When the source submits a document/message, it is encrypted for the journalist key and stored. (Note: sources can pre-encrypt their submission locally and upload that, in which case we don't further encrypt it again, but our impression is that this is rarely done).
If the journalist chooses to reply to source, that message is encrypted to the specific source and journalist (so journalists can read messages they sent). When a source logs in with their passphrase, we decrypt any journalist replies and display them to the source.
Currently this is all done using GPG, using a vendored copy of the unmaintained pretty_bad_protocol library: https://github.com/freedomofpress/securedrop/tree/develop/securedrop/pretty_bad_protocol.
== Migration to Sequoia ==
Any new source gets a keypair generated by Sequoia, which is stored in our SQLite database in armored format instead of the GPG keyring.
Upon upgrade we run a one-time migration that iterates over the GPG keyring, exporting public keys into our database.
When sources log in, we use their passphrase to export their secret key out of GPG and into our database as well.
We've also added some checks for SecureDrop admins to reject SHA-1 keys during installation using sq-keyring-linter.
To bring Sequoia into our Python application, we've written a small Rust crate ("redwood") that implements the encryption, decryption and key generation functions and can be exported to Python using the PyO3 bridge: https://github.com/freedomofpress/securedrop/tree/develop/redwood.
== Review request ==
Thanks to Wiktor who's already reviewed some of our code and Neal for some input on issues and people who replied to my questions in IRC.
We'd appreciate if anyone could take a look at our Sequoia-interfacing code, with a focus on the following areas:
* Are we creating PGP key pairs correctly? * Is this (armored text) a safe format to store keys in? * Are we generally using the correct Sequoia APIs / are we using those APIs correctly?
All of our Rust code is at https://github.com/freedomofpress/securedrop/tree/develop/redwood and the main Python<-->Rust integration is at https://github.com/freedomofpress/securedrop/blob/develop/securedrop/encryption.py.
And if there are any other concerns or potential issues that other migrations have encountered that we might have not considered.
== Thanks ==
As a general note, it has been fantastic to use Sequoia. So thank you to everyone who has worked on it!
-- Kunal, on behalf of the SecureDrop team