GPG subkeys marked with the "authenticate" capability can be used for public
key authentication with SSH. This is done using gpg-agent which, using the
--enable-ssh-support
option, can implement the agent protocol used by SSH.
A working gpg2 setup is required. It may be possible to use gpg 1.4 but with gpg-agent compiled from gpg2. If you are using OS X 10.9 (Mavericks) then you may find the instructions here useful.
For setup purposes, you also need to the openpgp2ssh
script; this can be
removed later if you wish. openpgp2ssh
is a perl script from the
monkeysphere project which transforms OpenPGP RSA keys into OpenSSH ones.
This requires the Crypt::OpenSSL::Bignum
perl module:
% sudo cpan install Crypt::OpenSSL::Bignum
% curl http://archive.monkeysphere.info/debian/pool/monkeysphere/m/monkeysphere/monkeysphere_0.36.orig.tar.gz |
> tar -x --strip-components 2 monkeysphere-0.36/src/openpgp2ssh
% chmod +x openpgp2ssh
% cp openpgp2ssh ~/bin
If you are using OS X then you will want to disable ssh-agent otherwise launchd will keep on spawning it whenever you do anything ssh-related:
% sudo launchctl unload -w /System/Library/LaunchAgents/org.openbsd.ssh-agent.plist
If you haven't already, then generate an authentication subkey with gpg --expert --edit-key 0xAF72A573
. Be sure to toggle authentication capability
on the subkey. For the rest of this document, as an example I will use my own
key, which has a keyid of AF72A573 with authentication subkey 2F959C28.
gpg-agent creates the environment variables GPG_AGENT_INFO
, SSH_AUTH_SOCK
and SSH_AGENT_PID
, which it prints out at startup.
% eval $( gpg-agent --daemon --disable-scdaemon --enable-ssh-support )
To identify the authentication subkey it is useful to have its fingerprint:
% gpg --list-secret-keys --with-colons --fingerprint --fingerprint 0xAF72A573 |
> awk -F: '$12 == "a" { getline; print $10 }'
56505466974969D71034D4F12A40F8F32F959C28
Export the secret key and convert into from an OpenPGP RSA key into one that SSH can understand:
% gpg \
> --export-options export-reset-subkey-passwd,export-minimal,no-export-attributes \
> --export-secret-subkeys 0x56505466974969D71034D4F12A40F8F32F959C28! |
> openpgp2ssh 56505466974969D71034D4F12A40F8F32F959C28 \
> > './Andrew Ho <andrewho@andrewho.co.uk>'
Add the key with ssh-add:
% ssh-add './Andrew Ho <andrewho@andrewho.co.uk>'
This will store a copy of the key in ~/.gnupg/private-keys-v1.d/
. It will
also add the keygrip of the subkey to ~/.gnupg/sshcontrol
.
To check that it has worked you can do ssh-add -l
. You can also use ssh-add
to generate the public key counterpart to be placed in the server's
authorized_keys file:
% ssh-add -L >> authorized_keys
% scp authorized_keys user@foo:.ssh/
It is useful to have the gpg-agent daemon ready for when you want to use it. It is also useful to be able to propagate the relevant environment variables across each session so that whenever you start a new shell it doesn't kill and respawn the daemon. This can be done by placing the following snippet in your shell's startup files (implemented, for example, here):
if [[ -a $HOME/.zshrc-ssh ]]; then
. $HOME/.zshrc-ssh
export GPG_AGENT_INFO SSH_AUTH_SOCK SSH_AGENT_PID
fi
kill -0 $SSH_AGENT_PID &> /dev/null
if [[ $? -eq 1 ]]; then
eval $( gpg-agent \
--daemon \
--enable-ssh-support \
--write-env-file=$HOME/.zshrc-ssh )
fi
This will tell gpg-agent to store the environment variables in ~/.zshrc-ssh
.
As each shell starts up, it will try to contact the daemon listed in those
environment variables. If it no longer exists (e.g. if the OS has been
restarted) then it will spawn a new daemon and rewrite the environment variables
to ~/.zshrc-ssh
. It is probably possible to achieve a similar feat using
launchd.
On the face of it, forwarding the agent over SSH works much the same as with the
native ssh-agent. Simply put the following in ~/.ssh/config
:
Host foo
ForwardAgent yes
The with agent forwarding is much the same as if you were to forward the native
ssh-agent: namely, that if you always reconnect to a long-running screen
session on login then $SSH_AUTH_SOCK
in each window will probably point to
a different (likely defunct) socket as the socket location changes with each
login. The answer is to have $SSH_AUTH_SOCK
point to a static location such
as ~/.ssh-agent-sock
. This is a symlink which points to the true location of
the socket which is updated on each login. This can be done with the following
code (again, implemented here):
if [[ $SSH_AUTH_SOCK == /tmp/* ]]; then
ln -sf $SSH_AUTH_SOCK $HOME/.ssh-agent-sock
export SSH_AUTH_SOCK=$HOME/.ssh-agent-sock
fi
I have a few questions about this.
Firstly though, my setup: Dell laptop running Manjaro Linux (Arch based distro) and gnupg 2.1.13(could be .15? Whichever is the newest)
Secondly, what I'm trying to do: 2 thing;. 1. have my gpg authentication subject, and most importantly 2. Have GitKraken recognize and use the ssh key output from the gpg authentication subject.
Things that I've found on the interwebs, that absolutely do not work, no matter what I try......: Monkeysphere, no matter how many different ways I try, I cannot get monkeysphere to actually install on my system, to date I've tried about 14 different ways.... Gnupg's own gpg2sshkey command, as of gnupg 2.1+, this has been removed and replaced with -export-ssh-key, this is supposed to strip the password and display the ssh formated public info, that part works, I can also use that command to report it into a id_rsa.pub file.... But now there is no way to get the id_rsa "private" key info. I've tried --export-secret-keys, and have been able to get an octet file name whatever I want, but I can't access because not knowing the password, --export-options -export-reset-subkey-passwd is no longer a valid command, so that's a dead end, unfortunately...working with this last bit has gotten me as close as I have gotten for id_rsa "private" key
What I've succeeded in doing, so far (after about 40 hrs of googling and trial and error....): I have used gpg2 --with-keygrip command to get and be able to place the gpg authentication subkey keygrip info into the gnupg sshcontrol file. I have been able to start the gpg-agent with the --enable-ssh-support, and I have been able to use the ssh RSA info from the --export-ssh-keys to connect and validate to GitHub through the CLI (btw, after so much trying this was huge win for me!!!! And at 3am out on my porch I "woohoo'd" right out loud.....it was awkward)
Here's where I'm currently stumped though.....GitKraken (and yes I know there are other git gui's available) to the most part it is a fully self contained program, that o my uses some of the .gitconfig, not all. In it's GUI interface, you can connect to github via ssh(only, no gpg option) by one of two ways. 1click the "use local ssh", in which it will create it's own ssh key internally, and connect you through that. Or 2, select and use your own public and private ssh key files.... So even though I was victorious with connecting my computer to github, I now have no physical private and public paired key files (although I could have a public one if I wanted, but it won't accept JUST the id_rsa.pub, it wants private too) to point GktKraken at.
So at this point, what in the world do I do? Have any thoughts, ideas, or suggestions for the making of paired ssh keys from the gpg authentication subkey for specific use inside the GitKraken program?