It’s nice and cosy and secure to have a separate GPG master key as described in many articles, for example https://wiki.debian.org/Subkeys. It’s also a good idea to set expiry dates on these keys so that if all else fails, at least they will only work for so long. But that means that every expiry interval you need to update the expiry dates to keep using the keys. And of course, like me, you totally remember how to do that a year (or a month, or 10 minutes) later. Right?

There is conflicting information about this, and GnuPG’s documentation and UI are terrible, so I wrote it down for us both.

For this recipe, you will need:

  • One backup of your original master key, ideally in ASCII-armoured (.asc) format
  • The passphrase for your original master key
  • One GnuPG 2, at least version 2.1
  • One Docker, optional

You can do all of this in a Docker container to keep things nicely separated. You don’t have to. I create a temporary GNUPGHOME anyway, just to be cautious.

docker run -ti --rm debian
apt-get update && apt-get install -y gnupg2

You can run the rest of the commands inside your shiny new container.

Create a temporary GPG home and import your master key backup.

export GNUPGHOME=$(mktemp -d)
gpg --import

Just paste your master key into the terminal (finish with Ctrl-D), or however else you want to get it into the container. Obviously look for people standing behind you scribbling furiously. You will be asked for your passphrase.

The output will include something like:

gpg: key 1234ABCD1234ABCD: public key "Your Name <[email protected]>" imported

Stick that key ID in a variable.

export ID=1234ABCD1234ABCD

Now edit the expiry date on the master key and all subkeys. I have 3 subkeys (encrypt, sign and auth), so that’s what you see in my example.

gpg --edit-key $ID
expire
1y
y
# Select however many subkeys you have
key 1
key 2
key 3
expire
y
1y
y
save

Optionally, make a fresh backup. Copying it somewhere is left as an exercise for the reader.

gpg -a --export-secret-key master > master-backup.asc

Push your updated public keys.

gpg --send-keys $ID

Clean up.

rm -rf $GNUPGHOME

Exit your shell and Docker will clean up the container.

That’s it! On your other machines, retrieve the updated public keys with the new expiry date.

gpg --recv-keys masterkeyid

Now if only I could work out how to get GPG agent forwarding to work…