Creating Secure GPG Keys

In this post I'll share the steps to generate keys for gpg in a secure way. The goal is to have an "air-gapped" primary key, complemented by a set of private keys for daily usage. This post is based on two older guides you can find here and here.

Ingredients

  • 2 USB-Sticks (> 4GB)
  • 1 SD card
  • A small .jpg portrait (< 5kB)

Tails

I am using the tails live OS as a poor man's air gapped environment. The USB stick holding tails should have never had direct contact with my day to day OS to minimize the risk of infection.

To achieve this I install tails manually from my regular OS to one of the prepared sticks. After booting into tails from that stick I am able to clone it to the second, pristine stick, using the built-in installer. While at it, I also create a persistent volume with a strong pass phrase.

I am re-using the first stick as a shuttle stick to transfer files between the regular OS and tails. After I have copied the portrait picture to it, I am ready to generate my keys and boot into tails.

Generating the primary key

$ gpg --gen-key --expert

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

I choose (8) RSA (set your own capabilities) and then disable the Encrypt capability. My primary key will be kept offline and I'll create a sub key for encryption later.

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

I select the largest available key size (4096).

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)

I do not specify an expiration date on my primary key. If it is set to expire in the future, one must remember to prolong it in time.

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

Real name: Max Mustermann
Email address: mustermann@muster-mail.de
Comment:
You selected this USER-ID:
    "Max Mustermann <max@mustermann.mail>"

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

My full name and private mail address are associated with this key identity.

You need a Passphrase to protect your secret key.

A strong pass phrase is the last line of defense protecting my primary key, in case it is compromised. As keyrings derived from my primary may have different (easier to remember) passwords, there is no reason to use a weak password.

Gnupg now creates a random key pair. The OS settings in tails are tweaked for faster generation of randomness out of the box. Therefore the key generation is rather quick.

Photo

Now I embed the small portrait .jpg to add an additional way to validate the key. As the gpg key will contain the image data, it should be rather small.

$ gpg --edit-key max@mustermann.mail
gpg> addphoto
Enter JPEG filename for photo ID:

I enter the path to my portrait on the shuttle stick and verify that it is the correct one.

Adding Sub-Keys

As I aim to keep my primary key offline, I now have to generate additional keys, one for each purpose (Signing, Encrypting and Authentication).

gpg> addkey
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

For each key, I enable only one capability. Once again I choose the largest key size. This time I am also setting an expiration date.

My keyring now contains the primary key, three sub keys, the user ID and portrait photo.

gpg> save

Finally I save the keyring and exit the gpg shell.

Exporting Key Files

Now I am creating backup files of my public key, the primary key and the sub keys.

$ gpg --armor --export max@mustermann.mail > public.gpg
$ gpg --armor --export-secret-keys max@mustermann.mail > primary.gpg
$ gpg --armor --export-secret-subkeys max@mustermann.mail > private.gpg

The exported public keys may and should be shared freely. The backup of the whole private key must be kept hidden and super-safe. The last command created an export comprised of only the sub keys without the primary key data, fit for use in my regular operating system.

As I had enabled the persistence feature of tails, my full keyring is stored in the encrypted part of the tails stick. In addition to that I am backing up the public and primary key file to a pristine SD card.

Using the shuttle stick I transfer just the public and sub keys (public.gpg and private.gpg) to my day to day OS and import them into my live keyring:

$ gpg --import private.gpg

Now I am ready to use gpg for encrypting and signing.

Distributing the key

Distributing my public key enables others to send encrypted messages to me and verify my signatures. Therefore I uploaded my public key to a well-known key server. The fingerprint of my key is

7EB1 6F93 DDA8 E920 4FE9  AA9D F481 983C 6131 9855
Written on October 10, 2015