Warning

The SKS keyserver network is under attack. The operators of the keyserver network recommend that you do not retrieve keys from the keyserver network.

Creating your GnuPG keys

By default, when you make your PGP keys, GnuPG creates a primary key with Certify and Signing [CS] capabilities and also creates a subkey with Encryption [E] capabilities. The problem with this is if your primary key ever gets stolen or lost you’ll have to revoke and recreate your keys. When you revoke your primary key you lose all the trust and reputation you’ve gained and you’ll also have to get everyone to import your new primary key. So what we’ll do is create a primary key with Certify [C] capabilities only, and then create subkeys for Encryption [E]and Signing [S]. We’ll then remove the primary key from the keyring and back it up off-line. This way if your keys get stolen, your master key is safe and you can simply revoke and regenerate the subkeys while keeping your primary key and your reputation.

Create your primary/certify key.

This key will then be used to create your encryption, signing and auth subkeys.

gpg --quick-gen-key "Chris Stevens <chris@pwned.com>" ed25519 cert 90d

You’ll be asked for a passphrase, then be asked to re-enter your passphrase. You’ll see the following output:

pub   ed25519 2020-12-26 [C] [expires: 2021-03-26]
      C13718F25749550B6504106ADF12A17CFEA01E81
uid                      Chris Stevens <chris@pwned.com>

Grab the fingerprint of the primary key. This is the 40 character string that shows up just under the “pub” output

Create a subkey for encryption

gpg --quick-add-key [fpr] cv25519 encr 90d

Create a subkey for signing

gpg --quick-add-key [fpr] ed25519 sign 90d

Optionally, create subkeys for auth

This will allow you to use GPG keys for authentication for SSH, though I haven’t played with this yet.

gpg --quick-add-key [fpr] ed25519 auth 90d

List fingerprints of all keys

gpg --with-subkey-fingerprints --list-key chris@pwned.com

Set key expiration

You can always change the length of the key expirations. For example, to change primary key expiration:

gpg --quick-set-expire [fpr] 180d # or 6m or 1y or 52w

Set expiration of all subkeys.

gpg --quick-set-expire [fpr] 6m \*

Set expiration of a specific subkey

gpg --quick-set-expire [fpr] 26w [subfpr]

Add additional UID’s

You can add additional names and e-mail addresses to your key:

gpg quick-add-uid chris@pwned.com "Chris Stevens <chris2@pwned.com>"

To edit your key information using the gpg ‘shell’, simply:

gpg --edit-key [fpr]

Export your keys

gpg --export-secret-key --armor [fpr]
gpg --export --armor [fpr]

Send your keys to a keyserver

The PGP keyservers are a hot mess. However there is a keyserver out there that you can publish your keys to that’s not part of the regular keyserver pool and is not affected by the same exploits. There are some limitations. You can’t see who’s signed your or other peoples keys, so the whole “web of trust” model is broken, but you can at least find keys if you know the fingerprints, or you can search by e-mail if you’ve explicitely allowed keys.openpgp.org to display your e-mail address.

gpg --keyserver keys.openpgp.org --send-key [fpr]|[keyid]

WKD - Web Key Discovery

This is a way of publishing keys for users of your domain without using the public keyservers. To publish all e-mail addresses from pwned.com to a WKD database:

mkdir -p .well-known/openpgpkey && cd .well-known
gpg --list-options show-only-fpr-mbox -k @pwned.com | /usr/lib/gnupg/gpg-wks-client -v --install-key

The .well-known directory needs to be published at openpgpkey.yourdomain.com. I used gitlab pages for this. I created a CNAME record for openpgpkey.pwned.com and pointed it to chrisstevens.gitlab.io. You’ll need to create an SSL cert for the openpgpkey subdomain.

Test Web Key Discovery

gpg -v --no-default-keyring --keyring /tmp/gpg-$$ --auto-key-locate clear,wkd --locate-keys chris@pwned.com

Encrypt a file to a recipient

gpg -er <recipient> <filename>

External Resources