gpg (and a bit about ecryptfs)

(January 2017)


Encrypt a file with a symmetric cipher using a passphrase:

$ gpg -ac myfile.txt

This produces myfile.txt.asc. -c is short for --symmetric. To send the out cipher text to STDOUT instead:

$ gpg -o - -ac myfile.txt

(The -a flag outputs ASCII rather than binary. ASCII is more portable; gpg ASCII output may be safely pasted into an email, for example.)

Note that after encrypting a file, gpg leaves the original in place, unmodified. Remember to securely delete the original file, if it shouldn’t be left sitting around in plain text. See shred(1), although it’s unclear how well secure delete utilities work on an SSD. Using an encrypted disk partition or directory may be a better bet.

Decrypt the file (plain text goes to STDOUT by default):

$ gpg -d myfile.txt.asc

Or, send the plain text to a file:

$ gpg -io myfile.txt -d myfile.txt.asc


Generate a public/private key pair:

$ gpg --gen-key

This generates a bunch of files in $HOME/.gnupg. List the keys with:

$ gpg --list-keys

In fact with gpg --list-keys and gpg --list-secret-keys, we see that GPG generated a number of keys:

Ideally, use of the master key pair should be confined to generating subkeys. We use subkeys for our day-to-day work.

We differentiate between signing and encryption keys. Signing keys protect our identity; the “web of trust” is tied to signing keys. Encryption keys protect our data. Encryption keys should be escrowed (backed up somewhere), but signing keys should not.

For some operations, we must refer to a “keyid”, which we can find with:

$ gpg --list-keys --keyid-format short
$ gpg --list-keys --keyid-format long

It’s a good idea to generate a revocation certificate now, at leisure, rather than when desperate:

$ gpg -ao $HOME/.gnupg/revocation_cert.asc --gen-revoke

Export your public key to a file:

$ gpg -ao me_pubkey.gpg --export

Spit the public key out to the command line:

$ gpg --armor --export
$ gpg --armor --export 08D01274

Send the key to a public keyserver:

$ gpg --send-keys --keyserver ABCDEF123456ABCD

Import someone else’s key from a file:

$ gpg --import someone_pubkey.gpg

Import someone else’s key from a public keyserver:

$ gpg --keyserver --search-keys 'John Smith'

(This, in itself, does not guarantee the true identity of someone! Verify the correctness of the key with the person to be sure.)

We may need outbound TCP port 11371 allowed on the firewall, although some keyservers listen on 443.

Encrypting a message for someone else:

$ gpg -ase -r -r myfile.txt

Note: without specifying ‘-r’, we won’t be able to decrypt our own message. Omitting this may be useful, if we want to make it impossible for anyone to later compel us to decrypt the message.

Signing vs Encrypting

When encrypting a message to someone, we use their public (encryption) key so only they can read it.

We sign a message with our private (signing) key. Someone can verify that we signed the message using our public (signing) key.

But there’s not necessarily much difference between a signing key and an encryption key, except how we use them. For that matter, public and private keys are the same, except in how we use them; we could encrypt a message with our public key, but it wouldn’t be very secret.

What if we want to verify our identity as the author of a public/plaintext message? We could encrypt the message with our public key, and distribute both the plaintext and ciphertext. Anyone would be able to see that decrypting the ciphertext using our public matches the plaintext, proving that we, the author, possesses the matching private key. Of course, this doubles the size of the message. Instead of sending ciphertext of the full message, we could send a cipher of a hash of the message. The simplest way to do this:

$ gpg --clearsign mymessage.txt

…which produces mymessage.txt.asc: the original plaintext with a PGP signature. See also the --sign and --detatch-sign flags. Or, to sent the ASCII-armored (by default the sig is output as OpenPGP-compatible binary) message signature to STDOUT:

$ gpg --output - --armor --sign mymessage.txt


$ gpg --armor --detach-sign mymessage.txt

To check a signed document:

$ gpg --verify mymessage.txt.asc

To debug what GPG is doing, and understand it better, use --list-packets:

$ gpg --export-secret-keys | gpg --list-packets


Subkeys make key management safer and easier. Subkeys are like normal keys, except that they’re bound to a master key pair. Subkeys bring two great benefits:

Imagine we have a laptop that might be stolen, but from which we still need to work. Keep the master key pair off the laptop; only install a subkey pair. If the laptop walks away, we revoke only the subkey, leaving the identity associated with our master key pair intact.

GnuPG actually uses a signing-only key as the master key, and creates an encryption subkey automatically. It used this subkey for normal operation.

Generating a subkey (signing and/or encryption):

$ gpg --edit-key
gpg> addkey
gpg> addkey
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
Your selection? 6
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 bits
Please specify how long the key should be valid.
	0 = key does not expire
	<n>  = key expires in n days
	<n>w = key expires in n weeks
	<n>m = key expires in n months
	<n>y = key expires in n years
Key is valid for? (0) 2y
Key expires at Sat 15 Jun 2019 08:32:47 PM EDT
Is this correct? (y/N) y
Really create? (y/N) y

Exporting a subkey for use on another device, while removing the master key:

$ gpg --export-secret-subkeys

Backing Up Encryption Keys (Key Escrow)

Various methods exist. For electronic backups, archiving ~/.gnupg/ suffices. For paper backups, a program called paperkey helps:

$ gpg --export-secret-key | paperkey

Note that output varies from one run of the command to the next, because the exported key is still protected by our passphrase.

Backing up the public keys is OK, but not strictly necessary. GnuPG and (re)generate the public keys from the private keys.

Encrypted Directories

Short of running full disk encryption, ecryptfs is a reasonable alternative to encrypt a particular directory. The ecryptfs-setup-private script make it easy to set up an encrypted $HOME/Private/ directory.

# apt-get install ecryptfs-utils
# modprobe ecryptfs
$ ecryptfs-setup-private

This creates ~/.Private (the encrypted directory “lower directory”) and ~/.Private (the unencrypted “upper directory” mount point). After logging out and logging in again:

$ mount | grep Private
/home/me/.Private on /home/me/Private type ecryptfs (rw,nosuid,nodev,relatime,ecryptfs_fnek_sig=a58f7aef132c31a7,ecryptfs_sig=318d1b73d90304a5,ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_unlink_sigs)

This directory should be automatically decrypted and mounted at login, and encrypted and unmounted at logout. RECORD THE MOUNT PASSPHRASE AND STORE IN A SAFE LOCATION. If the mount passphase file is lost, THERE IS NO WAY TO RECOVER THE ENCRYPTED DATA. Back up ~/.ecryptfs!

Note that ecryptfs is not reliable on network filesystems, including NFS.