Thomas H. PtacekI have watched a cryptographer of reasonably widespread renown spitball an attack on the PGP MDC, and then say “fuck it, I’m not going to spend time working on PGP”.
That’s roughly my take on where PGP is in the modern crypto firmament.21:41 PM - 18 May 2018
Due to the recent EFail disclosure, a new conversation has arisen over the security (it’s lacking) and usability (it’s complex) of PGP. This is a good conversation to have and, while I clearly have my own opinion, I welcome everyone’s thoughts in the comments below. I know the term “Post-PGP Age” is going to concern some members of the InfoSec community who will argue that strong, secure PGP clients are still the ideal solution for any use case, or at least the majority of them. My intention with this article is not to argue that PGP should die. Instead, I want to outline reasonable alternatives to PGP, of which readers may not be aware, so they can make an informed decision regarding their use case.
Cryptography professor Matthew Green has a great article detailing the technical issues with PGP from 2014 and Keybase lists a series of cryptographic issues with PGP. We’ll summarize the two most troubling issues but those articles are definitely worth a read.
The biggest concern with PGP is that the cryptography just isn’t sufficient by modern standards. Chiefly, PGP has no support for forward secrecy. Forward secrecy is a property of cryptosystems that maintains confidentiality even if secret keys used in the past are compromised in the future. Each session has a different secret key. In some cases, such as with Signal, every single message has a new session key so, if a key is compromised, it only affects that particular message. The rest of the conversation remains secret. Without forward secrecy in PGP, if an attacker gains control of either party’s private key, the entire history of the conversation is compromised.
Additionally, PGP does not employ authenticated encryption by default. Authenticated encryption is a property that combines the confidentiality and integrity properties of ciphertext into one operation. There is a Modification Detection Code (MDC) option supported in OpenPGP since 2001, but it must be opted-in by client implementations and many have not. A secure cryptosystem should enforce secure defaults. There is, of course, a valid argument about maintaining support for legacy systems but, after 15+ years, it should be acceptable to begin to require the option.
If you need to send encrypted email or secure sensitive files, what do you use if not PGP? Let’s look at what else is out there.
Let me kick off by saying that, while it is an available alternative, you should not choose OpenSSL. Public key encryption with OpenSSL is a lengthy process and there are simpler options with stronger security available. But, let’s look at how it would work. Replace any
%wrapped% text with an appropriate value.
1) Get the recipient’s public key in
pem format and go to step 2. If the key is in
rsa format, such as a key generated for SSH, the recipient must perform the following operations to convert their public and private keys:
openssl rsa -in %RSA PRIVKEY% -outform pem > %PRIVKEY%.pem openssl rsa -in %RSA PRIVKEY% -pubout -outform pem > %PUBKEY%.pem
2) As the sender, generate a random key:
openssl rand -base64 32 > %KEY%.bin
The 32 bytes in the
-base64 flag generates a 256-bit key.
3) The sender encrypts the key:
openssl rsautl -encrypt -inkey %PUBKEY%.pem -pubin -in %KEY%.bin -out %KEY%.bin.enc
4) The sender encrypts the file:
openssl enc -aes-256-cbc -salt -in %FILE_TO_ENCRYPT% -out %ENCRYPTED_FILE%.enc -pass file:%ABSOLUTE_PATH_TO_KEY%.bin
1) The sender transmits the file and encrypted key to the recipient. The recipient now decrypts the key:
openssl rsautl -decrypt -inkey %PRIVKEY%.pem -in %KEY%.bin.enc -out %KEY%.bin
6) And the recipient now decrypts the file:
openssl enc -d -aes-256-cbc -in %ENCRYPTED_FILE%.enc -out %FILE% -pass file:%ABSOLUTE_PATH_TO_KEY%.bin
So, we are left with 5-6 steps. Unless you use LibreSSL, AES-GCM modes will not be available to you, meaning you will have to select the
aes-256-cbc option when encrypting. AES-GCM is an authenticated encryption mode of AES, but authenticated encryption is not present in OpenSSL at the time of this article. If you must use OpenSSL, I recommend using the generally drop-in replacement, LibreSSL, with which you will have authenticated encryption modes.
With OpenSSL, we have a cumbersome process that doesn’t even solve (unless you use LibreSSL) one of our two primary cryptographic concerns with PGP. Let’s see what else we can use.
Saltpack is a new cryptographic format developed by Keybase that is built on top of the NaCL cryptographic library. Saltpack was designed specifically to improve upon the security shortcomings of PGP. Details on the encryption spec can be found here. It provides authenticated encryption and forward secrecy, among other guarantees like repudiable authentication. How do you use it? There are two options.
The sender and recipient must install Keybase.
1) Then, the sender encrypts the message:
keybase encrypt %RECIPIENT_KEYBASE_USERNAME% -m "%MESSAGE%" # Or, read the message in from a file keybase encrypt %RECIPIENT_KEYBASE_USERNAME < %MESSAGEFILE%
2) And the recipient decrypts the message:
keybase decrypt -m "%MESSAGE%" # Or, from a file keybase decrypt < %MESSAGEFILE%
There are also
verify commands available.
Currently, there are Saltpack packages in Go and Python. However, the Go package is the one used by Keybase and is fully featured. The Python package lags behind in terms of feature support, at least according to the Python package’s README on Github. You can still perform the same encryption, decryption, signing, and verifying with the Python package as with the Go package.
# Go go get github.com/keybase/saltpack # Python - requires Python 3 pip install saltpack
The Godocs contain example usage of the Go library, so let’s look at what the Python usage would look like:
1) The sender encrypts the message:
python3 -m saltpack encrypt "%RECIPIENT_PUBKEY%" -m "%MESSAGE%" > %ENCRYPTED%.enc
1) The receiver decrypts the message:
python3 -m saltpack decrypt "%RECIPIENT_PRIVKEY%" < %ENCRYPTED%.enc
Saltpack, especially via the Keybase client, is a great choice for users. A server can run these commands via a CLI, while users also have the option of Keybase’s apps or the Keybase website.
And finally, there are other alternatives, such as libpqcrypto, that require a development investment but could also serve as PGP replacements. There are also many NaCl clients that could be bootstrapped to support PGP-like behavior while taking advantage of stronger encryption. For “plug-and-play” encrypted email and file support, I recommend looking at Saltpack.
Thoughts on the article? Do you have other alternatives? Leave a comment!