3 Comments

Generating More Secure GPG Keys: A Step-by-Step Guide

This is part of a series on GNU Privacy Guard:

  1. Getting Started with GNU Privacy Guard
  2. Generating More Secure GPG Keys: Rationale
  3. Generating More Secure GPG Keys: A Step-by-Step Guide (this post)
  4. Using an OpenPGP Smartcard with GnuPG

gpg_subkeysIn this post, I’ll will cover the generation of a new GPG key and removal of the primary key, one of two mitigation strategies mentioned in the previous post. The next post in the series will demonstrate the second strategy: using this new key with a SmartCard.

A Secure Environment

We’ll start by generating a brand new key in a fairly secure environment. To do this we’ll want to boot into a LiveCD or LiveUSB environment to reduce the likelihood of malware interfering with the key generation process or stealing our new secrets. We’ll also want to do this in an offline environment. I happened to use a Tails Live USB Stick and an old netbook with wireless networking disabled so I’ll describe a similar process here.

The FSFE SmartCard Guide

Once Tails has booted, we can open a Terminal shell and start generating our new key.

We’ll follow along with roughly the approach recommended by Free Software Foundation Europe. The “Fellowship SmartCard” provided to FSFE Fellows implements the same OpenPGP SmartCard standard as the current version (Last changed: 2013-04-23 08:19:15) of their Card HowTo is quite good.

The guide recommends setting up your card reader first. We’ll worry about that later. We’re already offline and booted into a trusted live operating system, so we can jump right into generating the key.

Generating the Primary Key

Expert Mode

Invoke gpg --gen-key with the --expert flag to expose some additional menu items.

1
2
3
4
5
6
7
8
9
10
11
12
13
$ gpg --expert --gen-key
gpg (GnuPG) 1.4.12; Copyright (C) 2012 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)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
Your selection? 8

Capabilities

Choose (8) RSA (set your own capabilities). Then set the capabilities of the key to only Certify by toggling Signing and Encryption off.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify Encrypt
 
   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished
 
Your selection? s
 
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Certify Encrypt
 
   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished
 
Your selection? e
 
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Certify
 
   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished
 
Your selection? q

We’ll be using separate, short-lived subkeys for these purposes, but there are rare cases where you may be required to use this primary key for signing instead of a subkey certified by it (for example, if you need to prove ownership of this key to a party that doesn’t recognize subkeys).

As long as you have the private key material, it’s theoretically feasible to use keys for any purpose. But in practice, it simplifies things greatly if you have the capabilities you intend to use attached to the metadata for the keys when you generate them. Feel free to leave the Signing capability enabled if you’re worried about being hampered by this in the future.

Key-length

While the guide uses a 2048-bit key, we’ll use a 4096-bit key. Unless a larger key size isn’t well-suited for your needs (e.g. not being supported by software you need to use it with), it makes sense to use the largest key size available to ensure the key will be difficult to crack long into the future. And after all, a 4096-bit key is what Bruce Schneier is using these days.

1
2
3
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits

Expiration

Though the intent is to maintain this primary key more or less permanently — or at least until 4096-bit RSA is no longer thought to be secure — setting an expiration date on this key (for far into the future) may still be prudent, in the case (by that time) we have lost both the secret key and any copies we had of its revocation certificate. When you have the private key, you can always push an expiration date back, so let’s set this key to expire in 3 years. If we’re still using it when that date approaches, we can set a new expiration date and distribute the updated public key.

1
2
3
4
5
6
7
8
9
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) 3y
Key expires at Thu 03 Nov 2016 08:18:42 PM UTC
Is this correct? (y/N)y

uid

Next add a uid (name and e-mail).

1
2
3
4
5
6
7
8
9
10
11
You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
    "Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"
 
Real name: John Doe
Email address: john.doe@example.com
Comment:
You selected this USER-ID:
    "John Doe <john.doe@example.com>"
 
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

You can add additional uids later, if you wish.

Passphrase

1
2
3
You need a Passphrase to protect your secret key.
 
Enter passphrase:

Make sure to use a very strong passphrase here. Something long and hard to guess. If an attacker ever gets a copy of your secret key, this pass phrase should keep them from using it, or at least make it much more difficult.

Key Generation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 144A027B marked as ultimately trusted
public and secret key created and signed.
 
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2016-11-03
pub   4096R/144A027B 2013-11-04 [expires: 2016-11-03]
      Key fingerprint = 6E95 9C3A 35E7 6783 2BF4  BA32 21BB 9DA3 144A 027B
uid                  John Doe <john.doe@example.com>

It’s important to have a lot of entropy available to this process, otherwise the keys produced may be more easily predicted. If you’re following along and you’ve generated keys on other machines before, you may have been surprised by how quickly this one was created. This is in part due to the fact that Tails uses haveged as a source of additional entropy.

On other systems, you may get a message like:

1
2
Not enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need 87 more bytes)

And use mouse movements to generate this additional entropy.

Adding Subkeys

At this point, we have an OpenPGP key with only a 4096-bit RSA primary key for Certifying other keys.

1
2
3
4
5
6
7
8
9
10
11
$ gpg -k
/home/amnesia/.gnupg/pubring.gpg
--------------------------------
pub   4096R/144A027B 2013-11-04 [expires: 2016-11-03]
uid                  John Doe <john.doe@example.com>
 
$ gpg -K
/home/amnesia/.gnupg/secring.gpg
--------------------------------
sec   4096R/144A027B 2013-11-04 [expires: 2016-11-03]
uid                  John Doe <john.doe@example.com>

Now we can add the subkeys we’ll use for Signing, Encryption, and Authentication.

edit-key

Using --expert with gpg is like holding down alt/option on a Mac — it’s a good way to get at additional functionality that’s hidden from the default menus.

--edit-key should bring us to a prompt like this:

1
2
3
4
5
6
7
8
9
10
11
12
$ gpg --expert --edit-key john.doe@example.com
gpg (GnuPG) 1.4.12; Copyright (C) 2012 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.
 
pub  4096R/144A027B  created: 2013-11-04  expires: 2016-11-03  usage: C
                     trust: ultimate      validity: ultimate
[ultimate] (1). John Doe <john.doe@example.com>
 
gpg>

addkey

At this prompt, we’ll use addkey to add our subkeys. When we’re done, we should be left with a 4096-bit RSA primary key with the ‘certify’ capability and a three-year expiration and three 3072-bit RSA subkeys that expire six months from now with ‘sign’, ‘encrypt’, and ‘authenticate’ capabilities set accordingly.

We’ll invoke addkey for each of the subkeys we want to add.

1
2
3
4
5
6
7
8
gpg> addkey
Key is protected.
 
You need a passphrase to unlock the secret key for
user: "John Doe <john.doe@example.com>"
4096-bit RSA key, ID 144A027B, created 2013-11-04
 
Enter passphrase:

As we did with the primary key, we’ll toggle the capabilities of each key we add such that we’re left with only the one capability we want for that key.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
Your selection? 8
 
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt
 
   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished
 
Your selection? e
 
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign
 
   (S) Toggle the sign capability
   (E) Toggle the encrypt capability
   (A) Toggle the authenticate capability
   (Q) Finished
 
Your selection? q

The FSFE guide uses 1024-bit subkeys because that’s all the v1 SmartCards supported. The OpenPGP SmartCard v2 actually supports RSA keys up to 4096-bits, but only recent versions of GnuPG have support for working with keys that large on the SmartCard. With the 1.x.x branch of GnuPG, we can transfer RSA subkeys up to 3072 bits to the SmartCard v2. While the 2.x.x branch of GnuPG supports transferring 4096-bit keys, we’ll stick to 3072-bit keys to ensure compatibility with the older codebase.

1
2
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 3072

For reasons discussed in my Sure GPG Keys post, we’ll set these subkeys to expire relatively soon:

1
2
3
4
5
6
7
8
9
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) 6m
Key expires at Sat 03 May 2014 08:24:29 PM UTC
Is this correct? (y/N)y

After specifying the key type, capabilities, bit length, and expiration, we’ll generate the actual subkey:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Really create? (y/N) y
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.
 
Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy! (Need 268 more bytes)
+++++
 
Not enough random bytes available.  Please do some other work to give
the OS a chance to collect more entropy! (Need 8 more bytes)
+++++
 
pub  4096R/144A027B  created: 2013-11-04  expires: 2016-11-03  usage: C
                     trust: ultimate      validity: ultimate
sub  3072R/E02EDE61  created: 2013-11-04  expires: 2014-05-03  usage: S
[ultimate] (1). John Doe <john.doe@example.com>
 
gpg>

(Repeat this addkey process for the Encryption and Authentication subkeys)

While we’re still editing the complete key, we could also add addional uids, e.g. work e-mail address or other organizational addresses we might be known by. Typing adduid at the prompt will allow you to add additional uids.

We could even add a small (~120x144px, ~4KB JPEG) photo with addphoto if we wanted, but that’s probably not worth the effort of creating and bringing into our “air-gapped” environment right now.

When we’re finished, we’ll save the key to our keyring.

1
2
3
4
5
6
7
8
9
pub  4096R/144A027B  created: 2013-11-04  expires: 2016-11-03  usage: C
                     trust: ultimate      validity: ultimate
sub  3072R/E02EDE61  created: 2013-11-04  expires: 2014-05-03  usage: S
sub  3072R/A59563DA  created: 2013-11-04  expires: 2014-05-03  usage: E
sub  3072R/B2E31884  created: 2013-11-04  expires: 2014-05-03  usage: A
[ultimate] (1). John Doe <john.doe@example.com>
 
gpg> save
$

Creating Backups

Backing up Keyrings

Next, we’ll want to prepare some backups. The simplest way to back up all of the information we might want would be to copy our secret and public keyrings (~/.gnupg/secring.gpg and ~/.gnupg/pubring.gpg) to removable media (e.g. a thumbdrive or CD-R).

Backing Up Secret Keys & Generating a Revocation Certificate

We can make things a little more future-proof and a little more usable for ourselves though if we actually export our secret key…

1
$ gpg -a --export-secret-key john.doe@example.com > secret_key

…generate a revocation certificate…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ gpg -a --gen-revoke john.doe@example.com > revocation_cert.gpg
 
sec  4096R/144A027B 2013-11-04 John Doe <john.doe@example.com>
 
Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 1
Enter an optional description; end it with an empty line:
>
Reason for revocation: Key has been compromised
(No description given)
Is this okay? (y/N) y
 
You need a passphrase to unlock the secret key for
user: "John Doe <john.doe@example.com>"
4096-bit RSA key, ID 144A027B, created 2013-11-04
 
Revocation certificate created.
 
Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!
$

…and export our public key.

1
gpg -a --export john.doe@example.com > public_key.gpg

We’ll be sharing the public key later, but the secret key and revocation certificate are important to keep secret and safe. Put the secret key in a locked safe and guard it with Orks, or hire “Earl” to stand outside with a shotgun. Whatever you have to do.

The revocation certificate is also important to keep safe because if your primary key is revoked, you will lose all the Web of Trust signatures you will hopefully be carefully collecting for years to come. However, it’s more important that your revocation certificate should be accessible to you in case anything should ever happen to your primary secret key. It might be a good idea to keep a copy of this at your parents’ house, and another in a safe deposit box at your bank.

Paper Copies

Besides electronic media like thumbdrives and CD-Rs, it might also be a good idea to consider the enduring qualities of good, acid-free paper.

We could simply print off the ASCII-armored keys we exported, or we could use David Shaw’s Paperkey* to remove some of the redundant information from our secret key before printing. Unfortunately, Paperkey is not included in the packages pre-installed to the Tails live operating system we’re using.

Lack of SmartCard Support in Tails

Speaking of things lacking from the version of Tails we’re using, I found that using my OpenPGP SmartCard + Shell Token almost worked out of the box… but not quite. Eventually, I opted to use a Live USB stick from another Debian-based distro, CrunchBang, to handle getting the subkeys loaded onto the card. Since we’ve already created a backup of our keyrings to removable media, we can take that with us to this other, (mostly) isolated environment.

I say “mostly” because in order to get the SmartCard working with CrunchBang, I still had to install two packages not included in the default live environment. I was careful to do this when none of my secrets were on the machine, but it still is not ideal.

It may be worth creating a LiveCD/LiveUSB Linux distro specifically aimed at the purpose of generating GnuPG keys and working with OpenPGP SmartCards in an air-gapped environment…

For reference, here are the Tails bugs:
https://labs.riseup.net/code/issues/5931
https://labs.riseup.net/code/issues/6272

Removing the Primary Key

Even without a SmartCard, we can separate the primary key from these subkeys and gain some security. I’ve heard a set of subkeys like this referred to before as “laptop keys,” as in, keys you can keep on your laptop while the primary key secret remains safely locked away.

Unfortunately, the current process for removing the primary key (in both gpg 1.x.x and gpg 2.x.x) is non-obvious. For reference, we’re starting from a keychain that looks something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ gpg -k
/home/amnesia/.gnupg/pubring.gpg
--------------------------------
pub   4096R/144A027B 2013-11-04 [expires: 2016-11-03]
uid                  John Doe <john.doe@example.com>
sub   3072R/E02EDE61 2013-11-04 [expires: 2014-05-03]
sub   3072R/A59563DA 2013-11-04 [expires: 2014-05-03]
sub   3072R/B2E31884 2013-11-04 [expires: 2014-05-03]
 
$ gpg -K
/home/amnesia/.gnupg/secring.gpg
--------------------------------
sec   4096R/144A027B 2013-11-04 [expires: 2016-11-03]
uid                  John Doe <john.doe@example.com>
ssb   3072R/E02EDE61 2013-11-04
ssb   3072R/A59563DA 2013-11-04
ssb   3072R/B2E31884 2013-11-04

First we export just the subkey secrets:

1
$ gpg -a --export-secret-subkeys john.doe@example.com > secret_subkeys.gpg

Then we delete the entire (both primary and subkeys) secret part of our key from our keyring:

1
2
3
4
5
6
7
8
9
10
11
$ gpg --delete-secret-keys john.doe@example.com
gpg (GnuPG) 1.4.12; Copyright (C) 2012 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.
 
 
sec  4096R/144A027B 2013-11-04 John Doe <john.doe@example.com>
 
Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y
$

This leaves us with the public part in our ~/.gnupg/pubring.gpg:

1
2
3
4
5
6
7
8
$ gpg -k
/home/amnesia/.gnupg/pubring.gpg
--------------------------------
pub   4096R/144A027B 2013-11-04 [expires: 2016-11-03]
uid                  John Doe <john.doe@example.com>
sub   3072R/E02EDE61 2013-11-04 [expires: 2014-05-03]
sub   3072R/A59563DA 2013-11-04 [expires: 2014-05-03]
sub   3072R/B2E31884 2013-11-04 [expires: 2014-05-03]

But nothing in our ~/.gnupg/secring.gpg:

1
2
$ gpg -K
$

Then we re-import just the subkeys we exported (not the full secret key from earlier):

1
2
3
4
5
6
7
8
$ gpg --import secret_subkeys.gpg
gpg: key 144A027B: secret key imported
gpg: key 144A027B: "John Doe <john.doe@example.com>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1
$

And we’re left with our “laptop keys”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ gpg -k
/home/amnesia/.gnupg/pubring.gpg
--------------------------------
pub   4096R/144A027B 2013-11-04 [expires: 2016-11-03]
uid                  John Doe <john.doe@example.com>
sub   3072R/E02EDE61 2013-11-04 [expires: 2014-05-03]
sub   3072R/A59563DA 2013-11-04 [expires: 2014-05-03]
sub   3072R/B2E31884 2013-11-04 [expires: 2014-05-03]
 
$ gpg -K
/home/amnesia/.gnupg/secring.gpg
--------------------------------
sec#  4096R/144A027B 2013-11-04 [expires: 2016-11-03]
uid                  John Doe <john.doe@example.com>
ssb   3072R/E02EDE61 2013-11-04
ssb   3072R/A59563DA 2013-11-04
ssb   3072R/B2E31884 2013-11-04

Notice the # after sec: this denotes that the primary key secret is not in our keyring.

If we were not going to use a SmartCard to store these keys, we can export them and transfer them to our latop via removable media (USB stick).

1
2
$ gpg -a --export-secret-keys john.doe@example.com > laptop_keys_secret.gpg
$ gpg -a --export john.doe@example.com > laptop_keys_public.gpg

And import them onto our laptop:

1
2
3
4
5
6
7
8
9
10
11
$ gpg --import laptop_keys_public.gpg
gpg: key 144A027B: public key "John Doe <john.doe@example.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
$ gpg --import laptop_keys_secret.gpg
gpg: key 144A027B: secret key imported
gpg: key 144A027B: "John Doe <john.doe@example.com>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

If we wanted to make sure that even these subkeys couldn’t be read from our laptop if it were compromised, then we’d want to transfer them to a SmartCard instead. Stay tuned!


Read the rest of this series on GNU Privacy Guard:

  1. Getting Started with GNU Privacy Guard
  2. Generating More Secure GPG Keys: Rationale
  3. Generating More Secure GPG Keys: A Step-by-Step Guide (this post)
  4. Using a GPG Key with a SmartCard (coming 12/2013)