Use a YubiKey for SSH connections
This article is the third of a serie dealing with privacy on the Internet. I strongly recommend that you do the second part of this serie of articles (if you haven’t already done so) otherwise you will have a hard time following it. Technically it is not impossible but throughout these articles, the keys used will be the same (among others) and if you don’t have the same structure, it will be a real headache.
The daemon to manage private keys independently from any protocol (
gpg-agent) supports the OpenSSH
ssh-agent protocol, as well as Putty’s Pageant on Windows. This means it can be used instead of the traditional
ssh-agent. There are some differences from
ssh-agent, notably that
gpg-agent does not cache keys but converts it, encrypts and stores them persistently as GPG keys and then makes them available to SSH clients. Any existing SSH private keys that you’d like to keep in
gpg-agent should be deleted after they’ve been imported to the GPG agent.
When importing the key to
gpg-agent, you’ll be prompted for a passphrase to protect that key within GPG’s key store. You may want to use the same passphrase as the original’s SSH version. GPG can cache passphrases for a determined period as well as SSH. Note that when removing the old private key after importing to
gpg-agent, keep the
.pub key file around for use in specifying SSH identities.
Information and requirements
These elements are to be taken into consideration to follow this article:
- tools are installed and executed on Arch Linux.
Create the configuration
Copy the following snippet into
enable-ssh-support default-cache-ttl 60 max-cache-ttl 120 pinentry-program /usr/bin/pinentry-curses
cache-ttl options do not apply when using a YubiKey as a smartcard as the PIN is cached by the smartcard itself. Therefore, in order to clear the PIN from cache (smartcard equivalent to
max-cache-ttl), you need to unplug the YubiKey.
Copy the following snippet into the shell
rc file. Mine is located at
~/.config/fish/config.fish but for BASH it’s
set -x GPG_TTY (tty) set -x SSH_AUTH_SOCK (gpgconf --list-dirs agent-ssh-socket) gpgconf --launch gpg-agent gpg-connect-agent updatestartuptty /bye > /dev/null
Copy public key
It is not necessary to import the corresponding GPG public key in order to use SSH. Copy and paste the output from
ssh-add -L to the server’s
ssh-add -L ssh-ed25519 AAAA[...]
Save public key for identity file configuration (optional)
By default, SSH attempts to use all the identities available via the agent. It’s often a good idea to manage exactly which keys SSH will use to connect to a server, for example to separate different roles or to avoid being fingerprinted by untrusted SSH servers. I’ve already talked about that in this article.
The argument provided to
IdentityFile is traditionally the path to the private key file. For the YubiKey, it should point to the public key file, SSH will select the appropriate private key from those available via the SSH agent.
In the case of YubiKey usage, extract the public key from the SSH agent.
ssh-add -L > ~/.ssh/id_ed25519_yubico.pub
Add these lines at the end of your
~/.ssh/config (after other
Host * PubkeyAuthentication no IdentitiesOnly yes
Then you can explicitly associate this YubiKey-stored key to use it with a host. Copy the following snippet into the SSH configuration file (usually
Host example.com PubkeyAuthentication yes Hostname <IP address User <user> Port <port> IdentityFile ~/.ssh/id_ed25519_yubico.pub
Connect with public key authentication
If you have enabled the authentication touch, you will need to touch the YubiKey to complete the authentication process.
The third part is done. Now, we will see how to use a YubiKey to sign commits and tags for GitHub, Gitea or GitLab (it’s the exact same things).