mailpile / Mailpile

A free & open modern, fast email client with user-friendly encryption and privacy features
https://mailpile.is
Other
8.81k stars 1.02k forks source link

Making an Autocrypt key from any OpenPGP key #2137

Closed JackDca closed 6 years ago

JackDca commented 6 years ago

There are good reasons for a user who already has an OpenPGP key to use that same key when they transition to Autocrypt. Most important, the user's contacts will already have some degree of trust in that key either through signed email history, TOFU, direct verification and/or web of trust. Also, in a group of users who have already exchanged keys, and are transitioning one by one to Autocrypt, the non-transitioned members will at all times retain the ability to verify the signatures of the transitioned members; this would not be the case if new keys were adopted.

There is an issue in using an existing OpenPGP key with Autocrypt. The Spec (Autocrypt Level 1 specification, Release 1.0.0) section 2.1.1 requires that the keydata in an Autocrypt header MUST have exactly five packets: primary key, user id, user id self-signature, encryption subkey, and subkey self-signature. The keys generated by Mailpile comply with this requirement. But, many existing OpenPGP keys have multiple user ids, encryption subkeys, signatures and other packets, making them non-compliant. This is especially true for users who have taken the web of trust seriously and obtained user id signatures from others.

This issue can be addressed by stripping an existing OpenPGP key of all but the required five packets to create a minimal, Autocrypt-compliant key. This appears to be feasable based on reading RFC4880. That key will always have the same primary key packet as the source OpenPGP key, but the other packets may depend on the selection criteria used. If there are multiple Autocrypt-enabled accounts with different email addresses (i.e. user ids), the same OpenPGP key could be the source for multiple Autocrypt-compliant keys.

GnuPG indexes keys based on the primary key packet. If GnuPG imports a key that has the same primary key packet as a key that is already in the keychain, then GnuPG merges the new key with the existing one. GnuPG will not import the proposed minimal key as a separate key. This limitation could be handled by having a separate GnuPG keychain for each Autocrypt-enabled account, but that would add complexity.

The alternative proposed here is to use one keychain, and to extract the minimal key from the source OpenPGP key each time it is needed to construct an Autocrypt header, using the email address associated with the account (the Autocrypt from-addr) as the selector. In effect, the Autocrypt accounts[from-addr] structure (Spec 1.3.2) would use the primary key fingerprint and from-addr to point to the keydata, which would actually be stored in the GnuPG keychain.

Since signing is always done using the primary key, no special code would be needed in Mailpile to sign an outgoing email in an Autocrypt-compliant manner. (But note, the Spec is silent on whether unencrypted mail can/should be signed and whether clearsigning is acceptable.)

The Autocrypt key of a peer, ingested from an incoming Autocrypt header, could be stored in the same GnuPG keychain, even if a non-Autocrypt key from the same user, with the same primary key packet, already existed. The peers[addr] structure (Spec 1.3.1) would store the primary key fingerprint, the secondary encryption key fingerprint and addr. Those selectors would together point to the keydata stored in the keychain. In Mailpile, the keydata received from a peer by one account would be available to other accounts, which is convenient. When constructing a Autocrypt-Gossip header, the selectors would be used to extract each minimal key from its source OpenPGP key.

For Autocrypt compliance, encryption of messages to an Autocrypt peer must use the subkey specified (by its fingerprint) in peers[addr], even if there are other encryption subkeys in the OpenPGP key. Encryption by gpg with that subkey can be forced by specifying the recipient using the subkey fingerprint followed by "!" (Using the GNU Privacy Guard - version 2.2.7 - section 7 - By fingerprint), e.g.:

gpg -e -r E004A32FBA99A4BE! cleartext.txt

Implementing this use of the encryption subkey fingerprint would require relatively minor changes to Mailpile.

Although extraction of a minimal Autocrypt subkey from a OpenPGP key appears to be feasible based on RFC4880, there are enough details that the concept should be tested for greater certainty. The accompanying PR contains proof-of-concept code. This is not an Autocrypt implementation (there's no code to parse incoming Autocypt headers), just the minimum code needed to test extraction of the minimal key and creation of an Autocrypt header from it.

JackDca commented 6 years ago

@BjarniRunar - thanks for merging #2138 and for your comments. The VCard was used there as a quick-to-code way to turn on the Autocrypt header for test purposes. I know you have other ideas about storing the Autocrypt data. For myself, Mailpile is the first time I've encountered VCards and I do find them a bit messy, so maybe there are better ways. On the other hand, I have thought out how I would implement Autocrypt if given the task. One approach (admittedly, not the only one) is to fit it into the existing Mailpile structure with minimal additions and even fewer changes. I got thinking about stripping OpenPGP keys because (as well as just using it when creating a new Mailpile account) it could be useful in an implementation where there is no separate store for the Autocrypt keydata, which promotes the "minimal additions" goal. Likewise, putting the Autocrypt data into the existing VCards (or whatever other method the Mailpile of the future uses to manage other contact data). The question of whether VCards are the best way to store contact data is mostly orthogonal to the question of how to implement Autocrypt. I did the key stripping code because I didn't want to do anything that would duplicate or conflict with what you and/or @smari had done and guessed you had not done that! If the existing Autocrypt-related code is not ready to push to master, perhaps you could put it on an experimental branch in the Github so others could look at it, try it, and figure out how to contribute in a compatible way. (e.g. - A LookupHandler for finding keys in Autocrypt headers.) I know "coordination" is hard work. Thank you!

BjarniRunar commented 6 years ago

I'm going to close this issue as resolved, thank you for your hard work on this!

I'm planning to push up "stage 1" of Mailpile's Autocrypt support later today, which merges this code with work from @smari and myself - accounts which are configured to use Autocrypt for key exchange will be using this to minimize the header size and comply as closely as possible with the spec.