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>