Encrypting Files in a Post-PGP Age

Have you recently learned that PGP is not as secure as you had hoped? Looking for a simpler cryptographic tool? I don't blame you. Read on for alternatives.

May 26, 2018 - 6 minute read -
crypto

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.

What is the problem with PGP?

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.

What are my alternatives?

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.

OpenSSL

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

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.

Use the Keybase client

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 sign and verify commands available.

Use a Saltpack package for your programming language

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.

To install:

# 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.

Other

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!