I’ve steered clear of GPG for a while simply because I never implemented a reliable method of storing my keys. Now, with cloud storage, authenticated symmetric encryption, and hardware keys, I believe I can no longer worry about losing my keys. Forgetting the passphrase is a different matter, mind you.
I’ll be showing you how to create a reliable set of personal GnuPG keys you can use for authentication, authorisation, signatures, and encryption. These keys should stay with you for years to act as your sole source of truth. You do trust yourself, don’t you? 🙂
These examples will exist completely separately from your actual key so to speed up the tutorial I will use simple passwords. In your actual keys, well… you know the drill: use long passphrases that you generate from somewhere and then mutate the results. I usually suggest GRC Perfect Password Generator and some dice.
First, make sure you have GnuPG installed. This software provides a full implementation of the OpenPGP standard. I’m using version 2.1.18.
# apt install gnupg
And, we’ll use our own custom invocation of gpg just for this tutorial.
$ mkdir $HOME/gpgtutorial $ cd !$ $ alias gpgh="gpg --homedir=$HOME/gpgtutorial"
Let’s jump right into it. We’ll generate a key right now without a passphrase. This will use the batch functionality so we don’t have to answer any prompts. The terminal will appear to hang but that’s because entropy is being generated so wait a while for it to complete. This process took 2 minutes on my machine.
$ gpgh --batch --pinentry-mode loopback --passphrase '' --quick-generate-key "Antony Jepson (test account) <firstname.lastname@example.org>" gpg: keybox '/home/local/gpgtutorial/pubring.kbx' created [wait 2 minutes] gpg: /home/local/gpgtutorial/trustdb.gpg: trustdb created gpg: key 5F3720AC7BE7F124 marked as ultimately trusted gpg: directory '/home/local/gpgtutorial/openpgp-revocs.d' created gpg: revocation certificate stored as '/home/local/gpgtutorial/openpgp-revocs.d/B68449CF613EC70C13CC2ABE5F3720AC7BE7F124.rev'
Let’s look at the details of this new key and directory structure.
$ ls openpgp-revocs.d private-keys-v1.d pubring.kbx pubring.kbx~ trustdb.gpg
The openpgp-revocs.d directory contains your revocation certificates. You can use these to say you no longer want a certificate to be valid. The private-keys-v1.d directory contains your private keys. The pubring.kbx keybox file contains all your public keys with the ~ suffix representing the GPG agent’s backup. The trustdb.gpg file contains your personal web of trust.
$ gpgh --list-signatures 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 2021-03-27 /home/local/gpgtutorial/pubring.kbx ----------------------------------- pub rsa3072 2019-03-28 [SC] [expires: 2021-03-27] B68449CF613EC70C13CC2ABE5F3720AC7BE7F124 uid [ultimate] Antony Jepson (test account) <email@example.com> sig 3 5F3720AC7BE7F124 2019-03-28 Antony Jepson (test account) <firstname.lastname@example.org> sub rsa3072 2019-03-28 [E] sig 5F3720AC7BE7F124 2019-03-28 Antony Jepson (test account) <email@example.com>
You can see that this key was generated today and expires 1 year and 355 days from now. It consists of a public key that can be used for Signing and generating a Certificate. We have two signatures and the encryption signature has a trust level of 3. Finally, there’s a sub key that we can use for encryption.
I consider this initial set of keys the master keys. These are the keys you should do your utmost to keep safe. For day-to-day use, we will generate a set of sub keys for each required identity. For example, let’s generate a sub key to use with Github in order to sign our commits.
$ gpgh --edit-key "Antony Jepson" Secret key is available. sec rsa3072/5F3720AC7BE7F124 created: 2019-03-28 expires: 2021-03-27 usage: SC trust: ultimate validity: ultimate ssb rsa3072/0EDE2324F25F7767 created: 2019-03-28 expires: never usage: E [ultimate] (1). Antony Jepson (test account) <firstname.lastname@example.org> gpg> addkey Please select what kind of key you want: (3) DSA (sign only) (4) RSA (sign only) (5) Elgamal (encrypt only) (6) RSA (encrypt only) Your selection? 4 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) 2y Key expires at Sun 28 Mar 2021 09:50:21 BST Is this correct? (y/N) y Really create? (y/N) y 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. [Prompt for passphrase - I left this empty] sec rsa3072/5F3720AC7BE7F124 created: 2019-03-28 expires: 2021-03-27 usage: SC trust: ultimate validity: ultimate ssb rsa3072/0EDE2324F25F7767 created: 2019-03-28 expires: never usage: E ssb rsa3072/E3114D5381DE17CF created: 2019-03-29 expires: 2021-03-28 usage: S [ultimate] (1). Antony Jepson (test account) <email@example.com> gpg> quit Save changes? (y/N) y $ gpgh --list-keys --keyid-format long /home/local/gpgtutorial/pubring.kbx ----------------------------------- pub rsa3072/5F3720AC7BE7F124 2019-03-28 [SC] [expires: 2021-03-27] B68449CF613EC70C13CC2ABE5F3720AC7BE7F124 uid [ultimate] Antony Jepson (test account) <firstname.lastname@example.org> sub rsa3072/0EDE2324F25F7767 2019-03-28 [E] sub rsa3072/E3114D5381DE17CF 2019-03-29 [S] [expires: 2021-03-28]
Now we have a new subkey that can only be used for signing. Git already has a premise for using this key when creating commits.
$ git config --global user.signingkey E3114D5381DE17CF $ gpgh --armor --export E3114D5381DE17CF
Now you can paste the exported key into the relevant Github section in settings to sign your commits both on and off the website.
There’s a lot more to discover with GnuPG. I’ll be covering the process of keeping these keys secure in another post.