yubikey-agent is a seamless ssh-agent for YubiKeys.
- Easy to use. A one-command setup, one environment variable, and it just runs in the background.
- Indestructible. Tolerates unplugging, sleep, and suspend. Never needs restarting.
- Compatible. Provides a public key that works with all services and servers.
- Secure. The key is generated on the YubiKey and can't be extracted. Every session requires the PIN, every login requires a touch. Setup takes care of PUK and management key.
Written in pure Go, it's based on github.com/go-piv/piv-go and golang.org/x/crypto/ssh.
brew install yubikey-agent
brew services start yubikey-agent
yubikey-agent -setup # generate a new key on the YubiKey
Then add the following line to your ~/.zshrc
and restart the shell.
export SSH_AUTH_SOCK="$(brew --prefix)/var/run/yubikey-agent.sock"
On Arch, use the yubikey-agent
package from the AUR.
git clone https://aur.archlinux.org/yubikey-agent.git
cd yubikey-agent && makepkg -si
systemctl daemon-reload --user
sudo systemctl enable --now pcscd.socket
systemctl --user enable --now yubikey-agent
export SSH_AUTH_SOCK="${XDG_RUNTIME_DIR}/yubikey-agent/yubikey-agent.sock"
On NixOS unstable and 20.09 (unreleased at time of writing), you can
add this to your /etc/nixos/configuration.nix
:
services.yubikey-agent.enable = true;
This installs yubikey-agent
and sets up a systemd unit to start
yubikey-agent for you.
On other systems using nix, you can also install from nixpkgs:
nix-env -iA nixpkgs.yubikey-agent
This installs the software but does not install a systemd unit. You will have to set up service management manually (see below).
On other systemd-based Linux systems, follow the manual installation instructions.
Packaging contributions are very welcome.
Install the yubikey-agent
port.
Windows support is currently WIP.
It's possible to configure ssh-agent
s on a per-host basis.
For example to only use yubikey-agent
when connecting to example.com
, you'd add the following lines to ~/.ssh/config
instead of setting SSH_AUTH_SOCK
.
Host example.com
IdentityAgent /usr/local/var/run/yubikey-agent.sock
To use yubikey-agent
for all hosts but one, you'd add the following lines instead. In both cases, you can keep using ssh-add
to interact with the main ssh-agent
.
Host example.com
IdentityAgent $SSH_AUTH_SOCK
Host *
IdentityAgent /usr/local/var/run/yubikey-agent.sock
yubikey-agent
takes a persistent transaction so the YubiKey will cache the PIN after first use. Unfortunately, this makes the YubiKey PIV and PGP applets unavailable to any other applications, like gpg-agent
and Yubikey Manager. Our upstream is investigating solutions to this annoyance.
If you need yubikey-agent
to release its lock on the YubiKey, send it a hangup signal. Likewise, you might have to kill gpg-agent
after use for it to release its own lock.
killall -HUP yubikey-agent
This does not affect the FIDO2 functionality.
Use YubiKey Manager to change the PIN and PUK.
yubikey-agent -setup
sets the PUK to the same value as the PIN.
killall -HUP yubikey-agent
ykman piv access change-pin
ykman piv access change-puk
If the wrong PIN is entered incorrectly three times in a row, YubiKey Manager can be used to unlock it.
yubikey-agent -setup
sets the PUK to the same value as the PIN.
ykman piv unblock-pin
If the PUK is also entered incorrectly three times, the key is permanently irrecoverable. The YubiKey PIV applet can be reset with yubikey-agent --setup --really-delete-all-piv-keys
.
yubikey-agent
sets a new PIV management key, and then stores it in the pin-protected key metadata. If you need to retrieve it (for example, to modify the pin/puk retries with ykman
, you can do so with yubikey-agent -get-management-key
.
yubikey-agent
only officially supports YubiKeys set up with yubikey-agent -setup
.
In practice, any PIV token with an RSA or ECDSA P-256 key and certificate in the Authentication slot should work, with any PIN and touch policy. Simply skip the setup step and use ssh-add -L
to view the public key.
yubikey-agent -setup
generates a random Management Key and stores it in PIN-protected metadata.
By default yubikey-agent -setup
generates the private key on the hardware token (a YubiKey device). There's a --generate-key-on-computer-insecurely
switch that makes it generate the private key on the computer running yubikey-agent
, import the key to the YubiKey device and print the private key on the screen. This allows creating a backup of the private key in case you lose or damage your YubiKey. This option should only be used if you know what you're doing, because generating a key this way exposes it to being exfiltrated or manipulated when importing to the device which makes you less secure.
Recent versions of OpenSSH support using FIDO2 tokens directly. Since those are their own key type, they require server-side support, which has only recently reached Debian and GitHub.
FIDO2 SSH keys by default don't require a PIN, and require a private key file, acting more like a second factor. yubikey-agent
keys always require PINs and can be ported to a different machine simply by plugging in the YubiKey. (With recent enough tokens such as a YubiKey 5, a similar setup can be achieved by using the verify-required
and resident
options, after setting a FIDO2 PIN with YubiKey Manager: the private key file will still be required, but it can be regenerated from the YubiKey.)
gpg-agent
can act as an ssh-agent
, and it can use keys stored on the PGP applet of a YubiKey.
This requires a finicky setup process dealing with PGP keys and the gpg
UX, and seems to lose track of the YubiKey and require restarting all the time. Frankly, I've also had enough of PGP and GnuPG.
ssh-agent
can load PKCS#11 applets to interact with PIV tokens directly. There are two third-party PKCS#11 providers for YubiKeys (OpenSC and ykcs11) and one that ships with macOS (man 8 ssh-keychain
).
The UX of this solution is poor: it requires calling ssh-add
to load the PKCS#11 module and to unlock it with the PIN (as the agent has no way of requesting input from the client during use, a limitation that yubikey-agent
handles with pinentry
), and needs manual reloading every time the YubiKey is unplugged or the machine goes to sleep.
The ssh-agent that ships with macOS (which is pretty cool, as it starts on demand and is preconfigured in the environment) also has restrictions on where the .so
modules can be loaded from. It can see through symlinks, so a Homebrew-installed /usr/local/lib/libykcs11.dylib
won't work, while a hard copy at /usr/local/lib/libykcs11.copy.dylib
will.
/usr/lib/ssh-keychain.dylib
works out of the box, but only with RSA keys. Key generation is undocumented.
Secretive and SeKey are similar projects that use the Secure Enclave to store the private key and Touch ID for authorization. The Secure Enclave has so far a worse security track record compared to YubiKeys.
pivy-agent
is part of a suite of tools to work with PIV tokens. It's similar to yubikey-agent
, and inspired its design.
The main difference is that it requires unlocking via ssh-add -X
rather than using a graphical pinentry, and it caches the PIN in memory rather than relying on the device PIN policy. It's also written in C.
yubikey-agent
also aims to provide an even smoother setup process.