Table of Contents
Introduction
Secure Shell, Better known as SSH, is one of the most used tools to remotely manage servers. It allows developers and sysadmins around the world to login to a remote server as if they were there; however, as with any remote technology, there are security measures used to authenticate the user.
For anyone who as used SSH before, you probably know that there are two ways to authenticate the user:
- A password (very insecure and not recommended)
- A SSH public-private key pair
SSH uses ssh-agent
to manage ssh keys. On some systems, ssh-agent
isn’t used and SSH just directly serves identity files to the server.
PGP uses a very similar public-private key pair system, and is often used for various purposes. I won’t get into all the amazing ways PGP keys can be used (if you’re reading this, you probably already know some); however, it’s important to point out the different type of keys you can have:
- Certification key [C]
- Encryption key [E]
- Signing key [S]
- Authentication key [A]
Each one of these key types are used in different applications, but we’ll focus on the authentication key. If you don’t already have an authentication sub-key, you should generate one1.
We can ultimately use the PGP authentication key to replace our SSH keys. By replacing ssh-agent
with gpg-agent
we can have SSH use our GPG keys when connecting via SSH.
This is actually a relatively simple setup to get working. We have to:
- Point SSH to use
gpg-agent
for SSH authorization - Configure
gpg-agent
to serve the correct authentication key to SSH
Configure SSH to use gpg-agent
SSH uses the SSH_AUTH_SOCK
environment variable which points to UNIX socket used by the authentication agent. To get SSH to use gpg-agent
, we just need to have SSH_AUTH_SOCK
point to gpg-agent
’s socket.
Setting this up is rather simple. We can get gpg-agent
’s socket by running: gpgconf --list-dirs agent-ssh-socket
. We will also need to launch gpg-agent
by running: gpgconf --launch gpg-agent
.
To piece this together, add the following to your shell’s startup file2:
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
gpgconf --launch gpg-agent
Configuring gpg-agent
GPG still needs to be configured to properly serve the key to SSH.
First add enable-ssh-support
to ~/.gnupg/gpg-agent.conf
to enable SSH support:
echo 'enable-ssh-support' >> ~/.gnupg/gpg-agent.conf
At this point, SSH should be setup to use GPG keys; however, it’s good practice to specify which GPG key should be served. To do this, you have to first get the keygrip3 from your authentication subkey (the one that should be used for SSH).
To get the keygrip run: gpg -K --with-keygrip
which will produce an output with keygrips for your (sub)keys. Find the keygrip that corresponds to your authentication key, which will be shown with [A]
.
ssb rsa4096 2020-01-01 [A] [expires: 2022-01-01]
Keygrip = 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZABCD
Save the keygrip for the authentication key to ~/.gnupg/sshcontrol
:
$ echo '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZABCD' >> ~/.gnupg/sshcontrol
Getting Public SSH Key / Concluding notes
Everything should now be setup to authenticate using GPG keys. To get the public key that should be added to any server you wish to connect to, run gpg --export-ssh-key <user-id>
with your email or GPG key fingerprint. This will output a valid SSH public key that can be added to the authorized_keys
on the remote server(s).
The sshcontrol
file should contain the keys that should be serve by gpg-agent
, but should any need to be disabled in the future, you can prepend the keygrip with an !
mark to disable it.
If gpg-agent
is invoked (trying to authenticate a SSH session) without a sshcontrol
file, the file will be generated with the following comment:
# List of allowed ssh keys. Only keys present in this file are used
# in the SSH protocol. The ssh-add tool may add new entries to this
# file to enable them; you may also add them manually. Comment
# lines, like this one, as well as empty lines are ignored. Lines do
# have a certain length limit but this is not serious limitation as
# the format of the entries is fixed and checked by gpg-agent. A
# non-comment line starts with optional white spaces, followed by the
# keygrip of the key given as 40 hex digits, optionally followed by a
# caching TTL in seconds, and another optional field for arbitrary
# flags. Prepend the keygrip with an '!' mark to disable it.
-
There are many different guides on how to add a authorization subkey; however, I followed the YubiKey guide by drduh. ↩︎
-
The startup file for Bash is
~/.bashrc
, and Zsh uses~/.zshrc
. ↩︎ -
For an explanation between fingerprints and keygrips see this blog post. ↩︎