Table of Contents

Setting Up GPG Keys from Scratch


Disclaimer: This isn’t really supposed to be a comprehensive guide on how you should set up GPG, it’s more a record of what I did and why. This post will inevitably become outdated in the future so please use good judgement when it comes to your security.

Now that I’m self-hosting mail and moving off of ProtonMail, I figured I need to actually properly figure out GPG so I can send and receive encrypted emails. It will also be essential as I get further involved in free and open source software development since GPG is commonly used to sign software releases, among other things.

GPG is notorious for being quite complicated and not user-friendly. To assist in my GPG adventures, I enlisted the help of the Internet; mainly the Arch wiki.

I previously played around with GPG so I could use it for encrypting local backups and for signing git commits. I wasn’t using it seriously in any other respect so I began by rm -rfing my ~/.gnupg directory for a fresh start. I also set the GNUPGHOME environment variable to a directory on the SD card which I use specifically to store key data. On this SD card are key files, SSH keys, and now GPG keys all under LUKS encryption (don’t worry, I keep many copies of this SD card on other cards, USB sticks, and hard drives). Having a separate portable medium for my keys makes it so that I only have to worry about updating what’s on the card instead of what’s on all of the machines on which I am using GPG. It’s also technically a lot easier to hide or destroy, but I don’t see myself realistically needing to do that.

Generating the Master Key

Generating the master key is pretty straightforward.

$ gpg --full-gen-key --expert

--expert is required because I wanted to use Elliptic Curve Cryptography (ed25519 keys in particular) instead of RSA since ECC keys are smaller for a similar level of security. From the article linked above: “a 256-bit elliptic curve public key should provide comparable security to a 3072-bit RSA public key”. This will make typing in the key a lot easier and less error-prone should I have to restore it from paper backups. It’s also fewer bits to send over the Internet when sharing my public keys.

Generating a Revocation Certificate

It’s very important to have a revocation certificate since it’s what one publishes if their key is ever compromised or otherwise needs to be revoked. It’s essentially a way for one to tell the world “under no circumstances should you use or trust this key.” Unlike with subkeys, revoking a master key is much more significant since, once that becomes compromised or lost, one has to start again from scratch.

$ gpg --gen-revoke --armor --output=revocation-certificate.asc <user-id>

Where <user-id> in this case is the email I specified when generating my key:

Generating Subkeys

Typically, one shouldn’t be using their master key for every-day use. That’s because one’s master key is used for signing others’ keys, issuing new keys, and it’s the ultimate representation of one’s GPG identity. Instead, one should use subkeys as it’s far easier to revoke them and issue new ones in the case that they become compromised.

I generated one subkey specifically for signing and one subkey specifically for encryption:

$ gpg --edit-key --expert

I also set a one month expiry on both of those subkeys. While I think having an expiring master key is overkill for my uses and would be too much hassle, having subkeys expire is useful in the case that access to those subkeys is lost. This allows me to be less neurotic about backing up my subkeys compared to backing up my master key.

I chose a length of one month because it will keep me coming back to GPG regularly. This way, I can both make sure that my master key backups have not become corrupted without my knowledge and that I keep my GPG skills honed. It also gets me in the habit of doing monthly maintenance on my keyring.

Going Backup Crazy

To make sure that my master key and revocation certificate stay as private as possible and to minimize the risk of me ever losing access to them, I went a little bit crazy with the number of backup copies I made.

It’s extremely important to have physical copies of both because digital media can fail over time in ways that are hard to detect until one needs to access the data. I printed my revocation certificate directly since it’s just a short bit of ascii text and I printed out my master key using paperkey. Both of these pieces of paper went into my fire- and water-proof storage bag.

$ gpg --export-secret-key > privkey.gpg
$ paperkey --secret-key privkey.gpg --output printed.txt
$ lpr printed.txt
$ rm privkey.gpg printed.txt

I also made several digital copies of my private key. First, I exported my master key using:

$ gpg --export-secret-keys --armor > master.asc

Then, using GPG’s symmetric encryption capabilities, I encrypted both it and my revocation certificate using a completely new, randomly generated passphrase:

$ gpg -c master.asc
$ gpg -c revocation-certificate.asc
$ rm master.asc revocation-certificate.asc

I then put both of the new encrypted files: master.asc.gpg and revocation-certificate.asc.gpg onto two separate CDs—one went into my fireproof bag—and onto a floppy disk which also went into my fireproof bag. As soon as I have a free USB key, I’ll be making a copy on that too.

Uploading My Keys to a Keyserver

Using a keyserver allows for both easier access to my public keys for others as well as convenient offsite storage for the public part of my master key which is required to restore the private part of my master key using paperkey. A while back, an attack on the SKS keyserver network was discovered which caused many to become apprehensive about using keyservers. A solution proposed in the linked article was to use which is a new keyserver designed to mitigate the issues with the old keyservers. Following the given instructions, I uploaded my public keys so others should now be able to find me by searching for my email. Any time I need to use my master key (e.g. to sign another’s key or renew my subkeys), I can re-sync my public keys with the keyserver so they always stay up to date in others’ keyrings.

Configuring GPG and GPG-Agent

This is pretty simple and straightforward. Taking a few notes from the Arch wiki and setting options that I wanted to avoid having to type each time I ran gpg, I came up with the following configuration files:

keyserver hkps://
keyid-format long
personal-digest-preferences SHA512
cert-digest-algo SHA512
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
# Cache for a day
max-cache-ttl 86400
default-cache-ttl 86400
# Use curses-based pinentry program
pinentry-program /usr/bin/pinentry-curses

Deleting My Master Key

All of that backing up and making offline copies of my master key is so that I can do daily tasks with just my subkeys. To make this make sense, I have to delete my master key out of my keyring so it only exists offline until I need to use it. Since GnuPGv2.1, this is fairly straightforward:

$ gpg --list-keys --with-keygrip
$ rm /media/jbauer/keys/gpg/private-keys-v1.d/<keygrip>.key

After decrypting it from one of my backups, I can then later restore this key (which I’ll have to do at least once a month) by re-importing it with:

$ gpg --import master.asc


Without a doubt, using GPG is quite complicated. There are a variety of decisions that one can make depending on their desired level of security or anonymity which can be overwhelming if one doesn’t have much experience. I’ve spent probably 3 or 4 hours making sure that my processes are sound and making sure I’m doing everything right. To be honest, since I’m relatively new to using GPG seriously, I won’t be 100% sure I’m doing things right until I can experience using it in the real world.

This is my twenty-second post for the #100DaysToOffload challenge. You can learn more about this challenge over at