EN NL

Martijn's website

How I Should Use GPG

GPG, and the OpenPGP protocol it implements, are both quite unforgiving. You can find plenty of best practices, usage tips and tutorials on how to use it, and you’ll find plenty of best practices that aren’t enforced by the program, bad defaults or outdated recommendations. I have no illusion that this one of many blog posts on GPG will change anything. I however hope that you’ll maybe learn a few things about GPG, which you can combine with abundantly available other sources.¹

That said, I want to be clear that I won’t be writing about integration of GPG in other programs. I also assume that you already know what GPG is and what it is used for. If you don’t already, there are plenty of posts and resources out there that will give a better introduction. For example, the “GPG mini HOWTO”. This blog post will solely be about how to setup the gpg command line program and how to use it. I will also only use gpg version 2 (version 2.2.4 to be precise). If you don’t already have gpg version 2 or higher on your personal computer, I strongly suggest updating. On Ubuntu 18.04, version 2 is installed by default. On Ubuntu 16.04, version 2 is available with the gpg2 package.

Before executing any commands, I recommend first thoroughly reading the whole post and maybe to some further research into GPG.

So let’s get to it! Before we’ll even start to use gpg, we are going to edit our configuration file. Create ~/.gnupg/gpg.conf and append these lines:

# Use the longer key id format
keyid-format 0xlong
# Show the full key fingerprint
with-fingerprint
# Always show validity of user IDs (is default for some versions of gpg)
verify-options show-uid-validity
list-options show-uid-validity

# Set strong default preferences for new keys
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 CAMELLIA256 AES192 CAMELLIA192 AES CAMELLIA128

# GPG will use the highest ranked preferences that are compatible with
# the recipient's key.
personal-compress-preferences ZLIB BZIP2 ZIP Uncompressed
personal-digest-preferences SHA512 SHA384 SHA256
personal-cipher-preferences AES256 CAMELLIA256 TWOFISH AES192 CAMELLIA192 AES CAMELLIA128

The first few lines slightly changes the way gpg displays information about public keys. Here’s a comparison:

# The default format
pub   rsa4096 2018-10-21 [SC]
A95EF5275370376BE3B4B37A2DCBA7C834DF7D0F
uid           [ unknown] John Doe <johndoe@example.com>
sub   rsa4096 2018-10-21 [E] [expires: 2020-10-21]
# The customized format
pub   rsa4096/0x2DCBA7C834DF7D0F 2018-10-21 [SC]
Key fingerprint = A95E F527 5370 376B E3B4  B37A 2DCB A7C8 34DF 7D0F
uid                   [ unknown] John Doe <johndoe@example.com>
sub   rsa4096/0x76998D8F7B22B22E 2018-10-21 [E] [expires: 2020-10-21]

It is mostly personal preference, but it makes it easier to distinguish between subkeys. The second part of the configuration enforces more secure digest and cipher preferences.

Now we can make our new key pair. Since recent versions of gpg, we need to explicitly state that we want to have the full featured key generation dialog:

gpg (GnuPG) 2.2.4; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
	(1) RSA and RSA (default)
	(2) DSA and Elgamal
	(3) DSA (sign only)
	(4) RSA (sign only)

We will choose the default: an RSA key pair both for signing and encryption.

Your selection? 1
RSA keys may be between 1024 and 4096 bits long.

Computing power is basically never a bottleneck: always choose the highest supported keysize. Currently, that’s 4096-bits. This should be secure for a few decades.

What keysize do you want? (3072) 4096
Requested keysize is 4096 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

You can always edit the expiration time of your key pairs to postpone the expiration. It is useful to set an expiration date, so that your key will be automatically invalidated if you ever lose your private master key and don’t have a revocation certificate to invalidate your key immediately. We’ll go for 2 years.

Key is valid for? (0) 2y
Key expires at di 20 okt 2020 15:02:27 CEST
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: Kees Test
Email address: keestest@example.com
Comment:
You selected this USER-ID:
    "Kees Test <keestest@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O

If you use multiple email addresses, you can always add more later. gpg will now ask you to for a password for your secret key. Make sure that you use a safe password which you don’t already use for something else.²

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

gpg: key 0xD7518A5449C9D140 marked as ultimately trusted
gpg: revocation certificate stored as: '/home/testkees/.gnupg/openpgp-revocs.d/4B08B38EA98672661D485A4AD75
public and secret key created and signed.

pub   rsa4096/0xD7518A5449C9D140 2018-10-21 [SC] [expires: 2020-10-20]
      Key fingerprint = 4B08 B38E A986 7266 1D48  5A4A D751 8A54 49C9 D140
uid                   [ultimate] Kees Test <keestest@example.com>
sub   rsa4096/0xFB9E92ADD9565FA8 2018-10-21 [E] [expires: 2020-10-20]

We see here that gpg actually generated two key pairs instead of one. The first key pair is your main key: it is denoted with [SC]. You can use this key to sign messages or files: [S], and to sign other people their keys, create new subkeys and revoke subkeys or the main key itself: [C]. A notable feature that is missing is encryption: for this gpg automatically makes a subkey.

A subkey is essentially a separate key pair, but it is associated with a master key pair and used for a different purpose. As I already said, gpg by default uses a subkey for encryption. I would recommend to also use a subkey for signing, because this will allow you to generate your master key pair on a secure offline computer and then only export your subkeys to the computers you daily use. If your regular computer gets compromised, the attackers still don’t have your main key, so you can safely revoke your subkeys and generate new ones. The ideal setup is to put your subkeys on a smartcard and your main key on an offline and secure computer. Do note however, that even though an encryption subkey has been revoked, it can still be used to decrypt messages that were encrypted for that specific subkey.

To create a new subkey, we will enter the --edit-key menu:

$ gpg --edit-key keestest@example.com
gpg (GnuPG) 2.2.4; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Secret key is available.

sec  rsa4096/0xD7518A5449C9D140
     created: 2018-10-21  expires: 2020-10-20  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xFB9E92ADD9565FA8
     created: 2018-10-21  expires: 2020-10-20  usage: E
[ultimate] (1). Kees Test <keestest@example.com>

gpg>

You can do a whole lot more from this menu which I won’t cover here, if you want to know more, see the man page or type help.

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? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Requested keysize is 4096 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 di 20 okt 2020 16:12:39 CEST
Is this correct? (y/N) y
Really create? (y/N) y

Then gpg will ask you for a password.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.

sec  rsa4096/0xD7518A5449C9D140
     created: 2018-10-21  expires: 2020-10-20  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/0xFB9E92ADD9565FA8
     created: 2018-10-21  expires: 2020-10-20  usage: E
ssb  rsa4096/0xD0E9FD5D3BEE3A31
	 created: 2018-10-21  expires: 2020-10-20  usage: S
[ultimate] (1). Kees Test <keestest@example.com>

We have now created our key pair, where 0xD7518A5449C9D140 is the master key [SC], 0xFB9E92ADD9565FA8 is our encryption key [E], and 0xD0E9FD5D3BEE3A31 is our signing key [S]. gpg will automatically use the subkey instead of the master key for signing, but if you want to be sure, you can set the default-key option in your gpg.conf appropriately.

To communicate securely, your contacts will need to have your public keys: $ gpg --armor --output keestest@example.com.asc --export keestest@example.com You can share your public key with anyone: it can only be used to encrypt data for you to receive and to verify the signatures you made. You may also upload your public key to a keyserver, but watch out: this is permanent. You can’t delete anything from PGP keyservers.

You can send your public key any way you like to the people you would like to communicate with. But, you can’t immediately trust keys you’ve received via any channel. You will have to either verify the key’s fingerprint via a secure channel (for example, in person), or you have to verify this indirectly using the Web of Trust.

Commonly used commands

For all actions with gpg: the man page and a shell with tab autocompletion for command line flags and arguments will help a great deal.

To import your friends’ keys, you can simply do:

$ gpg --import johndoe@example.org.asc

To sign and encrypt a file:

$ gpg --sign --recipient $RECIPIENT_EMAIL --encrypt $FILE

You might also want to use the --armor flag to output it in OpenPGP’s ASCII container format. To backup your secret keys, or to export them to a different computer:

# Export all secret keys, including your master key:
$ gpg --armor --output gpg_secret_keys.asc --export-secret-keys
# Only export the secret subkeys:
$ gpg --armor --output gpg_secret_subkeys.asc --export-secret-subkeys

Some final remarks

The title of this post is How I (should) use GPG. With an emphasis on should. Creating a good GPG setup can be complex. And worst of all, you will probably realize the mistakes you’ve made only when you are using GPG a lot, after you’ve made your keys. It’s also a rather time-consuming and annoying process to create a new key pair and make sure that all the people you communicate with use the new keys. You will also need to keep the old keys around to decrypt old messages and files you may still need. So you’ll be stuck with your current keys for a while.

GPG and the OpenPGP protocol certainly aren’t user-friendly. They are also not the solution for mainstream private communications. Nonetheless, I still think that it is useful to have GPG and communicate using it as much as possible. Every extra encrypted message is one less sent in plaintext. GPG is also useful for things other than email communication: you might want to make encrypted backups or you might want to use GPG to cryptographically sign your Git commits, to make sure that nobody impersonates you.

Since this post became way too long, I sadly had to cut some things out. Most importantly, using a smartcard or a secure offline machine and using a GPG subkey for SSH authentication. I will try to write about these topics at another time.

Notes

¹ If you are interested in a more in-depth explanation of GnuPG, see the “mini” HowTo or the GnuPG manual.

² I prefer to use Diceware generated passphrases for these kind of things: it helps you to create easily memorizable and very strong passphrases.