GPG for SSH

I’m using the gpg-agent in place of the ssh-agent. I think this is a very interesting use because it eliminates the need for me to store my ssh key as a flat file:

ssh-add -l
4096 SHA256:rsOIZD3XP+Tvj+l5xrbRnxgvdg2qKL5agAxzPLT5rao (none) (RSA)
2048 SHA256:U6ETCKbdPbvgPMSjePS0jrGR3yMdhF9NC6MUHItynJc /Users/admin/.ssh/splice-dcos.pem (RSA)
...

You can see here that the top key is one that is generated by GPG and not associated with any particular file. That being said, I still have to use SSH keys that are given to me for work. The gpg-agent is able to handle this use case as well which is really what makes this process work in the first place. If I could only interact with my security bubble, this solution would have fallen on its face a long time ago.

You can configure your system to use the GPG Agent instead of the SSH Agent by adding some configuration to your ~/.zshrc:

# https://www.gnupg.org/documentation/manuals/gnupg/Agent-Examples.html
export GPG_TTY=$(tty)
unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
  export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
fi
# Kill running agent (don't)
#gpgconf --kill gpg-agent
# Connect the agent if it is not running.
gpg-connect-agent /bye
# GPG Agent

Make sure that you remove any lines that pertain to the SSH Agent in your config file as well. You can do a clean restart too if you don’t want to kill the SSH Agent process. I would recommend that actually because you will know for sure that the GPG Agent starts when you login in the future.

Messing with authentication methods was a scary prospect initially for me, but the transition has been transparent. If you’re considering this switch at all, I would encourage you to be brave (I say that because it would have been nice to hear when I did it).

Once that is configured, keys added with ssh-add will be added with the GPG Agent. You will be prompted to enter a password twice now. TODO: I’m not sure how gpg stores that password, but that password now protects that key.

When the GPG Agent adds an SSH key that is a file, it makes a record of it in ~/.gnupg/sshcontrol:

cat ~/.gnupg/sshcontrol 
# My manually added [A] key
# Fingerprints:  MD5:f5:92:e9:f4:09:d7:3d:b9:b8:eb:d7:8d:3c:d8:47:67
#                SHA256:rsOIZD3XP+Tvj+l5xrbRnxgvdg2qKL5agAxzPLT5rao
#                (none) (RSA)
078CF97299D5230502284C98ABF3A2983E24C51E
# RSA key added on: 2018-12-19 11:32:25
# Fingerprints:  MD5:d5:b3:57:5e:b1:eb:82:59:3c:43:09:de:7a:61:74:67
#                SHA256:U6ETCKbdPbvgPMSjePS0jrGR3yMdhF9NC6MUHItynJc
#                /Users/admin/.ssh/splice-dcos.pem (RSA)
5A38D99EF35D6FD1C5C7E729FB2C6F0F5E08FEFE 0
...

Note that there are comments in there, the agent adds those for files so you can easily identify the keys. It adds the SHA256 hash which is the output from ssh-add -l. It adds the MD5 checksum (ssh-add -l -E md5) which is the preferred method of identifying keys used by GitHub and GitLab (for some reason). It also calls out the file name at the time of addition. You can delete that file now. How cool is that?

Note there is only one active thing in that file. That is called a keygrip, and it is used to identify keys in GPG. TODO: Elaborate. You can get it from the GPG command line.

gpg -k --with-keygrip nik
pub   rsa4096/5BB58AFFDF8ED9D6 2018-12-19 [C] [expires: 2020-12-18]
      Key fingerprint = 1FD5 D4A1 F326 8A90 9A5C  BFC7 5BB5 8AFF DF8E D9D6
      Keygrip = 06924B0273717EAF55F5C8BACBD821E116A062BD
uid                 [ultimate] Nikhil Nygaard <[email protected]>
uid                 [ultimate] Nikhil Nygaard <[email protected]>
sub   rsa4096/1C434F4FBB0FE8B5 2018-12-19 [E] [expires: 2020-12-18]
      Keygrip = CBEE0C793F9FAE3841B775BD2461BB53F8509D6F
sub   rsa4096/6012253B4117B6DF 2018-12-19 [S] [expires: 2020-12-18]
      Keygrip = AA7FA31FB0599C72C77F27BE97679C74990A010F
sub   rsa4096/641EAE1AB4833D26 2018-12-19 [A] [expires: 2020-12-18]
      Keygrip = 078CF97299D5230502284C98ABF3A2983E24C51E
...

Note that it is the keygrip for my [A] key, the [A]uthentication key. This is the only key that is allowed to be used as an SSH key and can be separately invalidated in case of a breach. TODO: Article about key invalidation. There are many keygrip entries in ~/.gnupg/sshcontrol and each is associated with a specific pem file I need for work. TODO: I would like to know what happens when I initiate an SSH session and how GPG goes and gets the key that I need to authenticate with.