GPG and SSH keys are not something I ever really paid a huge amount of attention
to. I made a GPG key somewhere in 2018, used it for maybe two or three emails,
then only ever used it for encrypting my pass
store. It didn’t even have an
expiry. SSH keys were similar. I made one at my old job for connecting to my
first VPS and just used that for everything across several machines. It’s safe
to say that I wasn’t particularly conscious of security around them.
Last week one of my partners was showing me how she uses her GPG key to connect to hosts over SSH. She has much more intricate security practices than me, with lots of sub keys and redundancy and a Yubikey and all sorts of things are signed and verified. I understand very little of it but it certainly is impressive. My use case is far more humble however as I have two computers, a phone, and a VPS to worry about, rather than hundreds of machines spread across various organisations.
While working on a related project, I decided that now was as good a time as any to clean up the ancient keys and create a fresh set that I’d treat better, and I decided to have a go at combining the SSH key into the GPG key so I only had the one to keep track of and because it sounded cool. So:
# generate a new key (RSA, max size, 1y validity, etc.)
gpg --full-generate-key
# reencrypt my password store with the new key
pass init $key_id
For SSH, we want a sub key that is usable for authentication only (source):
# RSA key, max size, use the same expiration date as the main key
gpg --expert --edit-key $key_id
gpg> addkey
# export the public SSH key (for putting in ~/.ssh/authorized_keys)
gpg --export-ssh-key $key_id > gpg_rsa.pub
Now, ssh-agent
doesn’t look at GPG keys so it’s not going to be of any use
here. Instead, we want to make ssh
talk to our gpg-agent
instead as it can
emulate an OpenSSH agent provided the right environment variables are set
(source):
# in my fish config (adjust syntax for use in e.g. bash)
set -e SSH_AGENT_PID
set -x SSH_AUTH_SOCK (gpgconf --list-dirs agent-ssh-socket)
# so gpg-agent knows in what tty to prompt for key passwords
set -x GPG_TTY (tty)
gpg-connect-agent updatestartuptty /bye > /dev/null
That last command can also be added to your SSH config so it’s updated whenever you try to SSH from different terminals:
Match host * exec "gpg-connect-agent updatestartuptty /bye"
Lastly, the ‘keygrip’ of your authentication key needs to be added to
~/.gnupg/sshcontrol
so that gpg-agent
knows to use it for SSH connections:
gpg --list-keys --with-keygrip
The ‘keygrip’ value just needs to be added by itself as one line in the file for it to work.
Disable ssh-agent
however you had been running it and (probably) reboot and
now when you SSH to a host you should see the prompt for the password for the
GPG key before connecting!