YubiKey GPG-Agent Forwarding and Crypt4GH
Written by Dominik Pantůček on 2025-08-28
pgpyubikeyWorking on YubiKey support through GnuPG to enable working with Crypt4GH containers protected by private key stored in a trusted device, it seemed like a natural extension to keep the key locally and use it remotely - for example on a high-performance computing server.
Thanks to our previous work on LibAssuan support in
oarepo-c4gh package, YubiKey works
locally like a charm and all you need to do in order to unlock Crypt4GH containers is
to plug it in, have an OpenPGP app enabled on the token and ensure GnuPG installation
(at least version 2.4) recognizes it. These requirements are met by default on most
LTS operating systems
commonly used. The library recognizes the Curve25519
key provided by the
appliance and uses it without further ado. If required, the user has to explicitly
confirm the key usage by pressing the YubiKey button as they are used to.
The computing power of desktop computers and laptops most people use is limited though and therefore it would be very useful to allow the users to use their private keys in their hardware tokens and perform any computation on the encrypted data remotely on a more performant hardware. Some means of forwarding the connection to the YubiKey token need to be set up in order for this to work without compromising the private key in question.
Luckily as the oarepo-c4gh
is using gpg-agent
service for
communicating with YubiKey and its OpenPGP card application, all that is needed is to
forward the controlling socket of this service to the remote host. With the latest
versions of OpenSSH, it is pretty damn straightforward:
#!/bin/sh
ssh -R "/run/user/$USERID/gnupg/S.gpg-agent:$(gpgconf --list-dir agent-socket)" "$@"
Given the "$@"
argument means that the user can pass on normal SSH
arguments such as username and hostname and it will work. However there are some
security considerations here. Typically the advice is to always forward only the
"extra" socket of gpg-agent
. Trouble is that the "extra" socket cannot
list the private keys available and therefore requires more setup on the remote host.
The main socket allows listing the private keys - without their actual contents, of
course. It is obvious that people should use this type of forwarding only with a
hardware token like YubiKey and always only for one specific purpose - like here in our
case for opening Crypt4GH containers.
The question remains, how do we get the remote user's id? It should be known beforehand which means another SSH connection is to be made, but other than this little inconvenience, it is also very easy:
#!/bin/sh
USERID=`ssh -q "$@" id -u`
There are still some gotchas if you do not read the full documentation, the most imporant ones being:
- what if the
gpg-agent
is running on the remote host? - what if the socket path already exists (even though the agent is not running)?
- what if the GnuPG working directories do not exist?
For the first problem, we just ensure the agent gets killed. For the second one, we remove the path in question unconditionally. And for the third one we only need to perform any GnuPG operation - such as listing available keys. Yes, listing available keys where there are none - meaning we are listing an empty set of keys - is enough. That is another one-line script:
#!/bin/sh
ssh "$@" "gpg --list-keys ; gpgconf --kill gpg-agent ; rm -f /run/user/$USERID/gnupg/S.gpg-agent"
And yes, a convenient script can be created by putting all the snippets above into a single script below:
#!/bin/sh
USERID=`ssh -q "$@" id -u`
ssh "$@" "gpg --list-keys ; gpgconf --kill gpg-agent ; rm -f /run/user/$USERID/gnupg/S.gpg-agent"
ssh -R "/run/user/$USERID/gnupg/S.gpg-agent:$(gpgconf --list-dir agent-socket)" "$@"
It opens an interactive session and we can use local keys remotely. As a part of our
work on Crypt4GH support, this script is available as gpg-agent-forward.sh
in the oarepo-c4gh
repository and will get updated as new requirements
emerge.
In order to support strictly forwarding of the functionality required by our Crypt4GH implementation a custom network protocol is in the works and when that is released, no agent forwarding will be needed anymore in most scenarios.
Hope you liked our effort to keep your private keys truly private even when working on a remote supercomputer and if you wanna read more, see ya next time!