macOS YubiKey Setup
June 16 2023
How to use a YubiKey with SSH and GPG on macOS Ventura
I use a YubiKey on my personal devices to store my SSH and GPG keys. In theory this is for security reasons, but in practice I think this was just for fun.
Anyway, getting this set up on my MacBook hit way more issues than I anticipated, so I put together this post collecting everything I had to do. I’ll be assuming that you are using Homebrew, but note that this was done on an Intel MacBook so paths are likely different for Apple Silicon.
SSH
Creating *_sk Keys
SSH supports creating security-key-hosted *_sk keys, which are required if you want your SSH keys on your YubiKey.
Currently, these are id_ecdsa_sk and id_ed25519_sk.
See Yubico’s page on Securing SSH with FIDO2 for details on creating *_sk SSH keys on your YubiKey.
Using *_sk Keys
The built-in ssh on Ventura has support for *_sk keys removed for whatever reason.
You’ll need to install openssh from Homebrew to get support:
brew install openssh
This loses Apple’s Keychain integration, but as I don’t use that feature anyway this isn’t a loss.
Next, you’ll need to download the configuration file in Lorenz Bauer’s GitHub Gist.
This let’s us use Homebrew’s ssh-agent instead of the built-in version lacking *_sk support.
Place this file at Library/LaunchAgents/homebrew.com.openssh.ssh-agent.plist and run:
launchctl load Library/LaunchAgents/homebrew.com.openssh.ssh-agent.plist
Without this, attempts to add keys to the ssh-agent (e.g. ssh-add) will start the built-in ssh-agent and fail.
Forwarding SSH Keys
If your remote machine only has an *_sk type SSH key, you’ll need to forward your local keys for SSH operations (e.g. pushing git commits) as you can’t touch the remote YubiKey for validation.
To do so, you’ll want to make the following changes to ~/.ssh/config:
AddKeysToAgent yes
Host server_name
ForwardAgent yes
AddKeysToAgent automatically adds keys to your agent on use, while ForwardAgent makes your local keys available on the remote machine server_name.
I’ve put ForwardAgent under a Host because it’s not a great idea to be forwarding all of my keys by default.
See the ssh_config man page for more details on these options.
You can use ssh-add -L while connected to the remote machine to confirm your local keys are available.
Visual Studio Code
VSCode grabs the built-in ssh by default, but that can be fixed with a change to your settings.json:
{
"remote.SSH.path": "/usr/local/bin/ssh",
}
GPG
Adding a GPG Key to YubiKey
You’ll need to install gnupg from Homebrew:
brew install gnupg
See Yubico’s article Using Your YubiKey with OpenPGP for details on how to create GPG keys and then add them to your YubiKey.
pinentry
In order to use a GPG key on a YubiKey, you’ll have to enter a PIN.
By default, GPG was not configured correctly to ask for a PIN; instead, I would hit an IO error when GPG failed to show the PIN prompt.
I found the easiest fix to be configuring gpg-agent to use pinentry-mac, which can be installed with:
brew install pinentry-mac
This can then be activated by adding the following to ~/.gnupu/gpg-agent.conf:
pinentry-program /usr/local/bin/pinentry-mac
and running:
gpg-connect-agent reloadagent /bye
There are other versions of pinentry which can be configured based on preference (e.g. pinentry-curses or pinentry-tty).
Signing Git Commits
If you want to sign your git commits (and get the nice “Verified” label on GitHub), you just need to add the following to your ~/.config/git/config (or ~/.gitconfig):
[commit]
gpgsign = true
[user]
signingkey = PUBLIC_KEY
See the git manual for more details.
Oh My Zsh
Oh My Zsh includes plugins to start both ssh-agent and gpg-agent, which you can add in your ~/.zshrc:
plugins=(
...
)
# Assuming macOS is my laptop
# Need ssh-agent on client and gpg-agent on server
if [[ "$(uname)" == "Darwin" ]]; then
plugins+=(ssh-agent)
else
plugins+=(gpg-agent)
fi
See the ssh-agent README for more details on options.
Note that if the ssh-agent plugin is active on your remote machine it will override your forwarded keys!