PGP/GPG, setting up your keys

Root and subkeys

Your private key is your electronic identity. It's what you use to sign messages you send or decrypt messages which are interned only for you. If you lose this key you won't be able to do either. What's worse, if someone else obtains access to it it they'll be able to impersonate you and read encrypted messages to you. This is why it's critical to protect this key as you would any other form of critical, personal identification.

One step you can take is to use a subkey associated with your primary/root key. This will allow you to remove the root key from your system and keep it in a physically secure place, e.g. on an encrypted thumb-drive in your home safe. If the subkey is ever compromised you can revoke it separately and generate a new one without the hassle of having to create and share a new root key.

The idea is:

  • The root key is only used to work on your keys, e.g. create/modify/revoke subkeys
    • The private part of this key parir is removed from your system and kept in a safe place
  • Subkeys are used for day to day tasks that do not involve working on keys your keys, e.g. signing and encrypting email and files

If you ever need to modify your subkey, create another one, etc

  1. You retrieve the private part of the root key from the safe place
  2. Temporarily put it back on your computer
  3. Do the work you needed to, e.g. revoke your lost subkey and create a new one
  4. Remove the private part of the root key from your computer

Creating your keys

The process is:

  1. Create a primary/root key
  2. Use the root key to create some sub-keys
  3. Backup your root key and revocation certificate
  4. Remove the private part of the root key from your computer and put it in a safe place
  5. Use the spiffy new sub-key for your day to day tasks

Of course, this is GPG/PGP so doing the above is a PITA and not at all intuitive or clear. Don't worry, We'll walk you through it.

Create the root key

We'll be using gpg --full-generate-key

> gpg --full-generate-key
gpg (GnuPG) 2.2.19; Copyright (C) 2019 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.

gpg: directory '/home/jdoe/.gnupg' created
gpg: keybox '/home/jdoe/.gnupg/pubring.kbx' created
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)
  (14) Existing key from card
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072)
Requested keysize is 3072 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) 5y
Key expires at Sat 18 Oct 2025 08:14:20 AM EDT
Is this correct? (y/N) y

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

Real name: John Doe
Email address: jdoe@myemail.demo
Comment: Personal PGP key
You selected this USER-ID:
    "John Doe (Personal PGP key) <jdoe@myemail.demo>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
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: /home/jdoe/.gnupg/trustdb.gpg: trustdb created
gpg: key 388722F482101250 marked as ultimately trusted
gpg: directory '/home/jdoe/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/jdoe/.gnupg/openpgp-revocs.d/CB0F7D94E5D8218802BE334F388722F482101250.rev'
public and secret key created and signed.

pub   rsa3072 2020-10-19 [SC] [expires: 2025-10-18]
      CB0F7D94E5D8218802BE334F388722F482101250
uid                      John Doe (Personal PGP key) <jdoe@myemail.demo>
sub   rsa3072 2020-10-19 [E] [expires: 2025-10-18]

Create the subkeys

You'll note above that an Encryption subkey was automatically created to go with the root key. We're not going to use this one. In fact, we're going to delete it. Instead, we're going to create two additonal subkeys, one for signing and one for encryption. We're deleting the default subkey as we want both our subkeys to expire at the same time. (The default expires along with the root.) Also, it gives us the opportunity to show you gpg --edit-key.

The key command here is gpg --quick-add-key Note that 438 days from the time of this demo is 2021-12-31

> # Get the id of our root key
> gpg --keyid-format LONG --list-keys
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2025-10-18
/home/jdoe/.gnupg/pubring.kbx
----------------------------
pub   rsa3072/388722F482101250 2020-10-19 [SC] [expires: 2025-10-18]
      CB0F7D94E5D8218802BE334F388722F482101250
uid                 [ultimate] John Doe (Personal PGP key) <jdoe@myemail.demo>
sub   rsa3072/96A13CFE5BCEA9EE 2020-10-19 [E] [expires: 2025-10-18]

> # Create a subkey for signing
> gpg --quick-add-key CB0F7D94E5D8218802BE334F388722F482101250 rsa sign 438
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.

> # Create a subkey for encryption
> gpg --quick-add-key CB0F7D94E5D8218802BE334F388722F482101250 rsa encr 438
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 --keyid-format LONG --list-keys
/home/jdoe/.gnupg/pubring.kbx
----------------------------
pub   rsa3072/388722F482101250 2020-10-19 [SC] [expires: 2025-10-18]
      CB0F7D94E5D8218802BE334F388722F482101250
uid                 [ultimate] John Doe (Personal PGP key) <jdoe@myemail.demo>
sub   rsa3072/96A13CFE5BCEA9EE 2020-10-19 [E] [expires: 2025-10-18]
sub   rsa3072/B3DA891E5CC41CFB 2020-10-19 [S] [expires: 2021-12-31]
sub   rsa3072/AEC5403CC7ED9FD9 2020-10-19 [E] [expires: 2021-12-31]

Backup your root key and related files

We're going to be using gpg --export --armor and gpg --export-secret-keys --armor here. The armor argument tells gpg to use an ASCII format. Also note the use of --with-keygrip when listing the keys. The keygrip is a shorthand way for GPG to reference the key. We will use this to locate the file which contains the root, private key.

> # Export the keys in ASCII format to the current directory
> gpg --export --armor CB0F7D94E5D8218802BE334F388722F482101250 > pgp_root_public.asc
> gpg --export-secret-keys --armor CB0F7D94E5D8218802BE334F388722F482101250 > pgp_root_private.asc

> # Copy the root keys revocation certificate to the current directory
> cp ~/.gnupg/openpgp-revocs.d/CB0F7D94E5D8218802BE334F388722F482101250.rev .

> # Locate and copy the root's private key file to the current directory
> gpg --list-keys --with-keygrip
/home/jdoe/.gnupg/pubring.kbx
----------------------------
pub   rsa3072 2020-10-19 [SC] [expires: 2025-10-18]
      CB0F7D94E5D8218802BE334F388722F482101250
      Keygrip = 4AD50AC94C134533D8CFA0CCBA2EB7680D2CF3F5
uid           [ultimate] John Doe (Personal PGP key) <jdoe@myemail.demo>
sub   rsa3072 2020-10-19 [E] [expires: 2025-10-18]
      Keygrip = 8B2D1DBBC4326FB55709A37C063442ADB4EEA1CD
sub   rsa3072 2020-10-19 [S] [expires: 2021-12-31]
      Keygrip = 097CB6FEFAAF025CAE6E8934789E02873A77C11B
sub   rsa3072 2020-10-19 [E] [expires: 2021-12-31]
      Keygrip = 9D6E5FD048D6758B7FFEEB2606D440B321FB5380

> cp ~/.gnupg/private-keys-v1.d/4AD50AC94C134533D8CFA0CCBA2EB7680D2CF3F5.key .

> # Create a tar archive of the keys and revocation certification
> tar -czvf pgp_root_key_backup.tgz pgp_root_public.asc pgp_root_private.asc CB0F7D94E5D8218802BE334F388722F482101250.rev 4AD50AC94C134533D8CFA0CCBA2EB7680D2CF3F5.key
pgp_root_public.asc
pgp_root_private.asc
CB0F7D94E5D8218802BE334F388722F482101250.rev
4AD50AC94C134533D8CFA0CCBA2EB7680D2CF3F5.key

> # Cleanup up after ourselves
> rm pgp_root_public.asc pgp_root_private.asc CB0F7D94E5D8218802BE334F388722F482101250.rev 4AD50AC94C134533D8CFA0CCBA2EB7680D2CF3F5.key

You should move the tar file to external media and put it in a safe place. Note this is a move not simply a copy. i.e. delete the file from your computer once you've backed it up.

Remove the root private key from the system

Per above the name of the root private key file is based on the keygrip Simply locate and remove that file

> rm ~/.gnupg/private-keys-v1.d/4AD50AC94C134533D8CFA0CCBA2EB7680D2CF3F5.key

> gpg --keyid-format LONG --list-keys
/home/jdoe/.gnupg/pubring.kbx
----------------------------
pub   rsa3072/388722F482101250 2020-10-19 [SC] [expires: 2025-10-18]
      CB0F7D94E5D8218802BE334F388722F482101250
uid                 [ultimate] John Doe (Personal PGP key) <jdoe@myemail.demo>
sub   rsa3072/B3DA891E5CC41CFB 2020-10-19 [S] [expires: 2021-12-31]
sub   rsa3072/AEC5403CC7ED9FD9 2020-10-19 [E] [expires: 2021-12-31]

Performing operations on keys

As noted above, the root key should only be used to work on your keys. For example, you've lost your laptop with a subkey and now you need to revoke that subkey and create a new one. To do this, simply:

  1. Restore the private key file for the root key. In the above example is is ~/.gnupg/private-keys-v1.d/4AD50AC94C134533D8CFA0CCBA2EB7680D2CF3F5.key
  2. Perform the required work.
  3. Remove the private key file for the root key.