GPG Agent as SSH Agent

This will be a pretty curt post, intent is to remember how this was done. The rationale here is:

  • maintain physially separate ssh keypairs outside of GPG, mainly because as much as gpg is trusted the gpg-agent, documentation, and associated configuration files are a little confusing.
  • Utilize the gpg-agent for ssh-agent, providing you with the ability to have your key unlocked once per session and a consistent look and feel for the unlocking process via pinentry-curses.
  • use a difficult password for your ssh keypair but a more "straitforward" one for your gpg-agent to unlock the ssh keypair (maybe weird, explained below).

So, obviously first you need a gpg-key and gpg-agent set up, you should check out this article as it sets those things up as a prerequisite for pass.

Then set up an ssh keypair, use ed25519; ssh-keygen -t ed25519. Now I typically set a very long password of for this, which I don't particularly love to type this password at the beginning of my session, so gpg-agent can afford me the ability to add the keypair to my gpg-agent and use a different decryption key. This might sound weird, but it seems to make sense to me to lock down all of my ssh keypairs with extremely difficult passwords, as well as lock down my gpg keypair (and thus the agent password prompt) with an extremely difficult password... but use a simpler password for the ssh keypair once the gpg-agent is unlocked. May be confusing, so heres a temporal breakdown:

  • ssh keypair is created, use a 64 character or larger password (difficult)
  • gpg keypair is created, use a 64 character or larger password (difficult)
  • ssh keypair is added to gpg-agent, unlocked with 64 character password then protected via a 16 character smaller password (simpler)

To use the ssh keypair you'll have to get passed presumably your disk encryption, as well as the gpg-agent difficult password before using your simpler password.

Use GPG Agent as SSH Agent:

Assuming your gpg-agent is set up, we need to inform your shell that it will be your ssh-agent vim ~/.bashrc:

unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
  export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi

Then, likely, you'll want to restart your sesion/agent. Then add your ssh keypair to the gpg-agent:

ssh-add ~/.ssh/private_key

This will prompy you for the actual ssh keypair password. You can then add a simpler masked password with the passwd command. For each hash in your ~/.gnupg/sshcontrol you can:

echo passwd <hash> | gpg-connect-agent

Now when you attempt to use this keypair you'll be prompted via pinentry-curses (if you've got that configured in your gpg-agent.conf) instead of the normal ssh-agent prompt.

Anecdotally, this is my ~/.gnupg/gpg-agent.conf (which I've set to cache unlocked keys for long enough that it should last my entire session):

pinentry-program /usr/bin/pinentry-curses
max-cache-ttl 60480000
default-cache-ttl 60480000
max-cache-ttl-ssh 60480000
default-cache-ttl-ssh 60480000