Encrypting Files in a Post-PGP Age
Tags: crypto, security, encryption
Published: 2018-05-26 23:29:09

---
title: Encrypting Files in a Post-PGP Age
published: true
tags: crypto,security,encryption
canonical_url: https://blog.artis3nal.com/2018-05-26-encryption-post-pgp-age/
---

{% twitter 997593091094794241%}

Due to the recent [EFail disclosure](https://efail.de/), 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](https://blog.cryptographyengineering.com/2014/08/13/whats-matter-with-pgp/) detailing the technical issues with PGP from 2014 and Keybase lists a series of [cryptographic issues with PGP](https://saltpack.org/pgp-message-format-problems). 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](https://en.wikipedia.org/wiki/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](https://www.signal.org/), 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.

{% twitter 997231087108550658%}

Additionally, PGP does not employ [authenticated encryption](https://crypto.stackexchange.com/questions/12178/why-should-i-use-authenticated-encryption-instead-of-just-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](https://lists.gnupg.org/pipermail/gnupg-users/2018-May/060315.html) 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?

{% twitter 997426990805409793%}

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:

```bash
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:

```bash
openssl rand -base64 32 > %KEY%.bin
```

The 32 bytes in the `-base64` flag generates a 256-bit key.

3) The sender encrypts the key:

```bash
openssl rsautl -encrypt -inkey %PUBKEY%.pem -pubin -in %KEY%.bin -out %KEY%.bin.enc
```

4) The sender encrypts the file:

```bash
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:

```bash
openssl rsautl -decrypt -inkey %PRIVKEY%.pem -in %KEY%.bin.enc -out %KEY%.bin
```

6) And the recipient now decrypts the file:

```bash
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](https://www.libressl.org/), 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](https://saltpack.org/) is a new cryptographic format developed by [Keybase](https://keybase.io/) that is built on top of the [NaCL](https://nacl.cr.yp.to/) cryptographic library. Saltpack was designed specifically to improve upon the security shortcomings of PGP. Details on the encryption spec can be found [here](https://saltpack.org/encryption-format-v2). 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](https://keybase.io/download).

1) Then, the sender encrypts the message:

```bash
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:

```bash
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](https://godoc.org/github.com/keybase/saltpack) and [Python](https://github.com/keybase/saltpack-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:

```bash
# 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:

```bash
python3 -m saltpack encrypt "%RECIPIENT_PUBKEY%" -m "%MESSAGE%" > %ENCRYPTED%.enc
```

1) The receiver decrypts the message:

```bash
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](https://libpqcrypto.org/index.html), 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!