Skip to content

PGP key/subkey management

Contents

Creating the keyset

The strategy: create a primary secret key which is only used to issue and certify subkeys, which are actually used for encryption/signing/authorization. The Debian wiki has a good rundown on why this is desirable.

Create temporary working directory

Any time we’re working with the primary secret key, we’ll do so by setting GPG’s home directory to an ephemeral working directory (deleted on reboot):

export GNUPGHOME=$(mktemp -d -t)

Creating the secret key

gpg --expert --full-gen-key

Following the prompts:

  1. Select key type RSA (set your own capabilities)
  2. Select allowed actions
    • Disable Sign and Encrypt
    • Certify should be the only allowed capability
  3. Select keysize 4096 bits
  4. Select key expiration 0 = key does not expire.
  5. Enter user ID (name and email)
  6. Choose a strong passphrase (and back it up securely if you won’t remember it)

Creating subkeys

Generate a subkey each for the signing, encryption, and authentication actions:

gpg --expert --edit-key jon@jonwebb.dev

Once in the editing prompt, add 3 subkeys:

gpg> addkey

For each subkey:

Finally, write the subkeys to the main key:

gpg> save

Validate the generated keys:

gpg -K
/home/jon/.gnupg/pubring.kbx
----------------------------
sec   rsa4096 2023-01-05 [C]
      D35F9AA116CB89015A7A44EF4B540D953C59993B
uid           [ultimate] Jon Fake <jon@jonwebb.dev>
ssb   rsa4096 2023-01-05 [S] [expires: 2024-01-05]
ssb   rsa4096 2023-01-05 [E] [expires: 2024-01-05]
ssb   rsa4096 2023-01-05 [A] [expires: 2024-01-05]

Here’s what the acronyms stand for:

sec
Secret key
uid
User ID
ssb
Secret subkey

Backup

Get a semi-reliable form of digital media, and backup the following files (maybe > 1, in different locations):

Export & publish public key

gpg -o pubkey.asc -a --export jon@jonwebb.dev

This is the only one that’s ok to share. Put it on your website , or publish it to a keyserver if desired.

Export secret key + subkeys

gpg -o masterkey.asc -a --export-secret-keys jon@jonwebb.dev

This would be pretty bad to share. If someone steals it, the only thing between you and crypto hell is your passphrase.

Export subkeys (w/o secret keys)

gpg -o subkeys.asc -a --export-secret-subkeys jon@jonwebb.dev

This would be slightly less bad to share, since you still store the secret key required to create new keys, and you can revoke compromised subkeys.

Export revokation certificate

Store this in an additional location in the event the secret key is lost. You should probably print it to paper.

gpg -o revoke.asc --gen-revoke jon@jonwebb.dev

This would be annoying to share, since it could allow anyone to revoke your keys, necessitating a lot of work and an embarrasing blog post.

Still paranoid? Use paper.

Paper lasts hundreds of years , but the earliest known USB drive was created mere decades ago.

Nuke the working directory

gpg --delete-secret-key jon@jonwebb.dev
sudo reboot

Import working subkeys (“laptop” keypair)

Get your backup media and import the subkeys (the export without the secret key):

gpg --import subkeys.asc
gpg --edit-key jon@jonwebb.dev trust quit # trust ultimately when prompted

Validate the imported keys:

gpg -K
sec#  rsa4096 2023-01-05 [C]
      D35F9AA116CB89015A7A44EF4B540D953C59993B
uid           [ultimate] Jon Fake <jon@jonwebb.dev>
ssb   rsa4096 2023-01-05 [S] [expires: 2024-01-05]
ssb   rsa4096 2023-01-05 [E] [expires: 2024-01-05]
ssb   rsa4096 2023-01-05 [E] [expires: 2024-01-05]

The hash at the end of sec# means that the master, certifying key is not present. Success!

Now yeet your backup media back to the nether realm.

Renewing subkeys

Every year, your subkeys will expire, so they will have to be renewed with the secret key.

Create temporary working directory

export GNUPGHOME=$(mktemp -d -t)

Import & edit the secret key

Get your backup media and import the main secret key:

gpg --import masterkey.asc
gpg --edit-key jon@jonwebb.dev

In the GPG prompt, select each subkey (* appears next to selected keys):

gpg> key 1
gpg> key 2
gpg> key 3

Set a new expiration for the subkeys, and save:

gpg> expire
gpg> save

Backup public key:

gpg -o pubkey-$(date +%F).asc -a --export jon@jonwebb.dev # publish to your website/keyservers!

Now yeet your backup media back to the nether realm.

Nuke the working directory

gpg --delete-secret-key jon@jonwebb.dev
sudo reboot

Use the renewed subkeys

For systems that already possess subkeys, it’s only required to update the public key:

gpg --import pubkey-${BACKUP_DATE}.asc

Revoking the secret key

In the event your secret key is compromised or lost, it can be revoked using the certificate generated earlier.

gpg --import revoke.asc
gpg -o pubkey-$(date +%F).asc -a --export jon@jonwebb.dev # publish to your website/keyservers!

Revoking a subkey

In the event that one or more subkeys are compromised, they can be revoked individually.

Create temporary working directory

export GNUPGHOME=$(mktemp -d -t)

Import & edit the secret key

Get your backup media and import the main secret key:

gpg --import masterkey.asc
gpg --edit-key jon@jonwebb.dev

In the GPG prompt, select one or multiple subkeys to revoke (* appears next to selected keys):

gpg> key 1
gpg> key 2
gpg> key 3

Generate a revokation certificate for the subkeys, and save:

gpg> revkey
gpg> save

Now generate new subkeys as needed.

Backup public key:

gpg -o pubkey-$(date +%F).asc -a --export jon@jonwebb.dev # publish to your website/keyservers!

Now yeet your backup media back to the nether realm.

Nuke the working directory

gpg --delete-secret-key jon@jonwebb.dev
sudo reboot

To generate new subkeys, go back to steps

Side quest: backing secret key to ✨ paper ✨

paperkey allows creating a copy of only the actually secret portions of the secret key, which, combined with the public key (from a backup, your website, or a keyserver) can be used to restore the entire key.

Storing only the actually secret portions of the key means it can be reasonably backed up to paper/QR.

Create secret key paper backup

Using paperkey:

gpg --export-secret-key jon@jonwebb.dev | paperkey --output masterkey-paper.asc

Create QR code backup

Using paperkey and qrencode (generating multiple QR codes due to file size):

gpg --export-secret-key jon@jonwebb.dev | paperkey --output-type raw | qrencode --8bit -Sv 40 --o masterkey-paper.qr.png

Note: zbarimg expects data stored in multiple codes to be in the same image. If the QR codes are stored in multiple files, they can be concatenated:

convert masterkey-paper.qr-01.png masterkey-paper.qr-02.png +append master-key-paper.qr.png

Decode QR code backup with zbarimg

zbarigm --raw -Sbinary | paperkey --pubring public-key.asc | gpg --import

See the Arch wiki for additional useful instructions.