Table of Contents
- Introduction
- Configure SSH Server
- Forward Local GPG Agent Socket
- GPG Agent Command
- Debug Socket Forwarding
- References
Introduction
gpg-agent
is a daemon used to manage GPG secret (private) keys for the gpg
and gpgsm
programs. These programs interact with the gpg-agent
daemon through a socket to request the secret key and request for the secret key.
If the gpg-agent process has the key, it provides it to gpg. If not, it tries to load the encrypted key from your keyring and prompts you for the key’s passphrase. Once the agent has obtained the decrypted key, it will store in memory. Then it passes it to the GPG process. In addition to GPG secret keys, Gpg-agent can also store SSH keys and provide them to SSH processes, like the ssh-agent
program that comes with SSH.
There are 2 sockets through which programs like gpg
and gpgsm
communicates in order to retrieve secret keys. First agent-socket
is used by local process to communicate with gpg-agent and the second one is agent-extra-socket
which is a more restricted socket can be used by remote machine in case of socket forwarding.
GPG v2.1 enables you to forward the gpg-agent to a remote system. That means that you can keep your secret keys on a local machine.
You need at least GnuPG 2.1.1 on both systems.
Configure SSH Server
We first need to configure SSH server on remote machine to enable automatic removal of stale sockets when connecting (or forwarding GPG socket) to the remote machine. Otherwise you will first have to remove the existing socket on the remote machine before forwarding works.
This can be automated by adding the following line to /etc/ssh/sshd_config
file:
StreamLocalBindUnlink yes
Forward Local GPG Agent Socket
Let’s say the remote machine needs an SSH key stored on our local machine in the GPG keyring in order to sign a commit before pushing to Git.
So we forward gpg-agent socket which is located at /run/user/1000/gnupg/S.gpg-agent
to remote machine through SSH tunnel using -R
option which can forward any type of gpg-agent socket and remote machine uses the forwarded socket instead of local one. So the remote machine will interact with our forwarded gpg-agent which contain secret keys.
ssh -R <remote socket path>:<local socket path> hostname
We can find the location of GPG socket using the following command:
gpgconf --list-dir agent-socket
Then replace the default SSH socket used by the SSH program to retrieve SSH keys by the forwarded GPG Agent socket:
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
GPG agent tries to load the encrypted key from your local GPG keyring using forwarded socket and prompts you for the key’s passphrase if the key is protected. Once the agent has obtained the decrypted key, it will store in memory. Then it passes it to the SSH program.
Since the ssh-agent protocol does not contain a mechanism for telling the GPG agent on which display/terminal it is running, gpg-agent’s ssh-support will use the TTY or X display where gpg-agent has been started. So to update the display to the current one add the following line in your .bashrc
file or whatever initialization file is used for all shell invocations:
export GPG_TTY=$(tty)
gpg-connect-agent updatestartuptty /bye >/dev/null
gpg-agent
configuration options can be define in .gnupg/gpg-agent.conf
file for permanent application. For example if we wants to decrypt a GPG secret key from a shell then we need to use a terminal based pinentry program. This can be changed by adding the pinentry-program /usr/bin/pinentry-tty
to gpg-agent configuration file. Also make sure that pinentry-tty
program exist on your system, if not install it using your package manager.
Here are some other options often used:
# Enable gpg-agent to manage keys instead of ssh-agent by SSH client
enable-ssh-support
# Change default pinentry program
# pinentry-program /usr/bin/pinentry-qt
# Set the time a cache entry is valid to n seconds.
default-cache-ttl 3600
# SSH password cache time
default-cache-ttl-ssh 3600
max-cache-ttl-ssh 3600
A full list of gpg-agent configuration options can be found here.
GPG Agent Command
The gpg-agent is automatically started on demand by gpg
, gpgsm
, gpgconf
, or gpg-connect-agent
and there is no reason to start it manually. But we can start it using:
gpg-connect-agent /bye
# OR
gpgconf --launch gpg-agent
Reload gpg-agent:
gpg-connect-agent reloadagent /bye
You can manually terminate the currently-running gpg-agent:
gpgconf --kill gpg-agent
Debug Socket Forwarding
When connecting to a remote machine, we can use the -v
option to display information about the forwarding socket:
ssh -v -R <remote socket path>:<local socket path> hostname
Sometimes on a remote machine we need to delete the socket created by remote gpg-agent. This happens when the remote gpg-agent is started or restarted after forwarding the local gpg-agent through the SSH tunnel.
References
https://wiki.gnupg.org/AgentForwarding
https://unix.stackexchange.com/questions/188668/how-does-gpg-agent-work - How does GPG agent work?