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!