Using GPG with a YubiKey

Update: Added a warning in the commands list to edit key before putting it on the card, updated backup stuff, fixed some command Update: zshrc changes

While PGP has some issues, it is currently the only viable solution for Git commit signing (there is some work being done on signing commits with Minisign, its level of integration is nowhere near that of GPG). Due to that, I recently read this guide, which seemed quite nice at first, given I have a YubiKey. However, I found some issues with it ‒ the actual Git commit signing, as well as, later on when I tried that as well, the SSH key authentication, would not work.

T.: Now, you could go on trying to explain the amendments you made to the instructions in the original guide, or you just put a nicely commented script and some config files in here.
fc17: I could, but…
T.: But what? You'd even have the advantage of this information staying relevant even if the linked blog post goes down.
L: Are you going to argue all day?
T.: No, lmao. So, dear reader of this post, here's that script I (editor's note: we (T.'s note on editor's note: nobody allowed you to write stuff into what I say, F., and this is little more than a shameless plug of the fact you contributed a bit to the script as well)) wrote:

# Don't actually run this as a script
# Assumes you're on macOS and have `brew` aliased to a sudo command that switches you to the separate user you use for Homebrew

# Install some stuff
brew 'brew install gpg ykman'

# Upgrade from 2fa lite to actual 2fa (you will now be required to touch it every time you perform an operation (after entering the passphrase))
ykman openpgp keys set-touch enc on
ykman openpgp keys set-touch sig on
ykman openpgp keys set-touch aut on

# switch to a temporary directory for our next actions
cd $(mktemp -d)

# keygen
gpg --expert --full-gen-key # RSA is lame; use ECC with curve25519
# Now copy the key ID you get somewhere towards the end into your clipboard
export KEYID="paste clipboard here"

# Generate subkeys
gpg --expert --edit-key ${KEYID}
# addkey three times, one for encrypting, authentication (use the one where you set your own caps, disable signing, and enable auth) and signing each, use ECC and curve25519 again
# now quit with `quit`

# Generate a backup
gpg --armor --export-secret-keys ${KEYID} > mastersub.key
# Put this somewhere, make a paper backup, maybe with a QR code, Idc

# Get your public key and put it somewhere nice
gpg --armor --export ${KEYID} > /somewhere/nice/myusername.asc

# Set your YK smartcard up (defaults are 123456 and 12345678)
gpg --card-edit
# Now admin, then passwd, also don't make this a literal PIN, use an actual passphrase from your password manager or something
# maybe also name, lang and login
# Now quit with `quit`

# The exciting part
# DO ANNOTATIONS AND STUFF BEFORE THIS! YOU WON'T BE ABLE TO EDIT YOUR KEY AFTERWARDS! (Ya need those for Keyoxide)
gpg --edit-key ${KEYID}
# key 1, keytocard, key 1, key 2, keytocard, key 2, key 3, keytocard, save

# Set up Git
git config --global user.signingkey ${KEYID}
git config --global commit.gpgsign true
# On other machines, after transferring the public key over
gpg --import /somewhere/nice/myusername.asc

# Add stuff to the config files as shown below

# Initialize stuff
. ~/.zshrc

# Keep your public SSH key in a nice place
ssh-add -L > ~/.ssh/yubikey.pub

# Make WKD (sauce: https://www.kuketz-blog.de/gnupg-web-key-directory-wkd-einrichten/)
mkdir -p .well-known/openpgpkey/yourdomain.xyz/hu
touch .well-known/openpgpkey/yourdomain.xyz/policy
gpg --with-wkd-hash --fingerprint ${KEYID} # Copy the hash before the @yourdomain.xyz
gpg --no-armor --export ${KEYID} > .well-known/openpgpkey/yourdomain.xyz/hu/yourclipboardhere
# Now put the .well-known into / of openpgpkey.yourdomain.xyz

~/.gnupg/gnupg-agent.conf

use-standard-socket
enable-ssh-support

~/.zshrc

gpgconf --kill gpg-agent
gpg --card-status > /dev/null
gpg-connect-agent updatestartuptty /bye > /dev/null
export "SSH_AUTH_SOCK=/Users/artemis/.gnupg/S.gpg-agent.ssh"
alias git-commit='gpg --sign "$(mktemp)" && git commit' # makes Git commit signing work properly