Recently got told off for using password-less SSH keys, with the excuse that they’re all stored on an encrypted hard drive—this isn’t even true anymore, though, since my desktop HDD isn’t encrypted like it used to be.

I’ve also learned that gpg-agent can also do SSH keys. Since I run gpg-agent all the time anyway for signing e-mail messages, it’s easy to have it doing SSH keys too. Using SSH agent forwarding, only my local machine has to see any keys. Anything from Emacs to a terminal SSHing out from my local machine will pop up an X11 password entry dialog (if the key isn’t cached already), and if I ssh from a remote machine to somewhere else, the same X11 dialog will pop up as the agent gets tunneled back automatically.

With the key only stored on two local machines, there’s no need for loads of SSH keys to selectively disable in the case of compromise: one for my two trusted machines, another for use with PuTTY on friends’ machines, and another for my git server on untrusted machines.

Daemon setup

Put this in .xinitrc to get gpg-agent running (from the Arch Wiki):

gnupginf="${HOME}/.gnupg/gpg-agent.info"

if pgrep -u "${USER}" gpg-agent >/dev/null 2>&1; then
    eval `cat $gnupginf`
    eval `cut -d= -f1 $gnupginf | xargs echo export`
else
    eval `gpg-agent --enable-ssh-support --daemon`
fi

~/.gnupg/gpg-agent.conf:

,# Cache settings
default-cache-ttl 10800
default-cache-ttl-ssh 10800

,# Environment file
write-env-file /home/swhitton/.gnupg/gpg-agent.info

,# Keyboard control
,#no-grab

,# PIN entry program
,#pinentry-program /usr/bin/pinentry-curses
,#pinentry-program /usr/bin/pinentry-qt4
pinentry-program /usr/bin/pinentry-gtk-2

In .ssh/config add the line ForwardAgent yes under connections to trusted machines that can re-use your authentication. You will want ForwardAgent no under Host * but make sure this block comes at the end of .ssh/config or the ‘no’ will take precedence over the ‘yes’.

Key setup

I’d like to follow Arch Wiki’s advice to use an ecdsa key, but sshd on Debian Stable doesn’t support this atm, so we’re going with RSA. Because of how we are going to use gpg-agent, the key can and should have a long and random and inconvenient passphrase—it is only going to be typed once per OS installation. I’m using a 20 char one generated by my password manager yapet. Default key length is fine.

$ ssh-keygen -t rsa -C"$(id -un)@$(hostname)-$(date --rfc-3339=date)"

Put the key on the remote server using existing key setup:

$ ssh-copy-id athena

This should now be the default key but it’s easier to add it to .ssh/config:

Host athena
...
ForwardAgent yes
IdentityFile ~/.ssh/id_rsa

We now need to add the key to gpg-agent. Restart your X session to get it running and then execute

$ ssh-add .ssh/id_rsa

You’ll have to type in your long passphrase, and then you’ll be prompted (twice ofc) for a new one by gpg-agent. This is the passphrase you’ll be typing on a regular basis to unlock the ssh key for use, so make it more practical/memorable.

That’s it, everything should work. Time for me to go and clean up my extremely messy ~/.ssh/ on various machines to complete the setup.