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 ~/.gnupg/gpg-agent.conf
.
enable-ssh-support
default-cache-ttl 60
max-cache-ttl 120
pinentry-program /usr/bin/pinentry-curses
The 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 default-cache-ttl
and max-cache-ttl
), you need to unplug the YubiKey.
Replace agents
Copy the following snippet into the shell rc
file. Mine is located at ~/.config/fish/config.fish
but for BASH it’s ~/.bashrc
.
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 authorized_keys
file.
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
directives).
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 ~/.ssh/config
).
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.
ssh user@example.com
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).