SSH authentication with your PGP key
A few weeks ago I learned that a few of my colleagues were using PGP. I myself started using PGP around 2003, using the GnuPG implementation. However, since I didn't know many people who used it my usage slowly faded after a few years. In 2009 I shortly picked it up again by creating a new key to phase out SHA-1, but that was also of short duration. Thanks to my colleagues, I'm now starting to use GnuPG again. My key is still the same as created in 2009: 610DB834.
I noticed that both my PGP-key and my SSH-keys use the RSA-algorithm, so I started wondering whether it was possible to use my PGP-key to authenticate myself to SSH-servers. After some Googling it seemed possible, but not very straightforward. In the end I managed to get it working, thanks to the very friendly support of Werner Koch (the main developer of GnuPG). Since it is not very straightforward I will document my findings here for future reference.
Adding an authentication key
First add an authentication subkey to your PGP-key, as it is apparently a best practice to use subkeys for each type of usage. To do so you need to start
gpg with the
--expert flag like this:
# where 610DB834 is the id of my key gpg --expert --edit-key 610DB834
When you are in
addkey and type '8' to choose
(8) RSA (set your own capabilities). This option let's you manually configure the new key. Then type (each time followed by
Q, so that it says 'Current allowed actions: Authenticate'. Then choose a keysize (I use 4096) and an expiration date (5 years from now for example) and wait for the key to be created. Finally
save to save your key. Your authentication-subkey is now ready.
Getting it working on the client
Now that we have a new authentication subkey on our PGP key, we can configure everything so that we can use our PGP key for SSH authentication. Sadly enough, this is not as straightforward as I had hoped for. At least not if you are using the current stable version of GnuPG (2.0.x). Werner Koch explained on the mailinglist that it should be rather easy with GnuPG 2.1, which is currently in beta.
As of GnuPG 2.1 the gpg-agent will be used to store all the keys. So to set-up everything, you only have to start gpg-agent with the
--enable-ssh-support option and add the 'keygrip' of your authentication key to the ~/.gnupg/sshcontrol file and you are done.
Sidenote. What is a 'keygrip'? As explained by Werner:
That is a protocol neutral way to identify a public key. It is a hash over the actual public key parameters. It is GnuPG specific but for example, pkcs#15 uses a similar technique. To compute it, you should use the respective Libgcrypt function.
When you prefer to use the current stable version of GnuPG it takes a few additional steps. The problem is that your key is not available to gpg-agent to be used for SSH-authentication, so you need to get it in the gpg-agent. One method to do this is by installing
monkeysphere (available from the ubuntu repos). After installing this, you can run the command
monkeysphere subkey-to-ssh-agent (or it's short form:
monkeysphere s). Monkeysphere will then extract your private authentication key from GnuPG, run it through the
openpgp2ssh-script to convert it into the correct format, and then add it to gpg-agent using the standard
ssh-add-command. After you have ran that command your authentication subkey will (also) be stored by gpg-agent and it will be added to the
~/.gnupg/sshcontrol-file so you can use it for SSH-authentication. (As with GnuPG 2.1, make sure that your gpg-agent is started with the --enable-ssh-support flag.)
If you prefer to use GNOME keyring, a similar solution is possible. The easiest solution is to simply run the aforementioned
monkeysphere subkey-to-ssh-agent-command. However, you will have to do this every time you log on again. This is because the regular
ssh-agent doesn't "remember" keys which are added using
ssh-add (while gpg-agent really copies them and stores them safely).
This problem can be solved by manually extracting your key, converting it, setting a new passphrase and storing it with the correct name in your
~/.ssh/-directory. By doing this GNOME keyring will automatically pick up the key. To do this execute the following commands (where C83CBC1B is my subkey):
cd ~/.ssh/ # export the key without a passphrase (the openpgp2ssh script # can't handle encrypted keys) gpg2 --export-options export-reset-subkey-passwd,export-minimal,\ no-export-attributes --export-secret-subkeys --no-armor \ 0xC83CBC1B! > C83CBC1B.key # convert the raw key to the correct format openpgp2ssh C83CBC1B < C83CBC1B.key > C83CBC1B # remove the exported raw key rm C83CBC1B.key # set the correct permissions for the private key chmod 600 C83CBC1B # add back a passphrase to the key ssh-keygen -f C83CBC1B -p
After doing this you will have your PGP key in the correct format inside your SSH-directory. However, for GNOME keyring to automatically pick up your key you also need to add the public key as C83CBC1B.pub. (see the next section)
Getting the key on the server
Before you can log on to a server using your PGP key, you also have to add it on the server. More correctly, you have to add your public key to the
~/.ssh/authorized_keys-file. So how do you obtain the public key of your authentication subkey?
Luckily that is rather easy. After you have added your key to gpg-agent or GNOME keyring you can simply run
ssh-add -L and the public keys for all your loaded keys will be shown. Pick the correct one, add it into the authorized_keys-file on the server and you are done!
side note: while I was searching for information about this I regularly found references to the gpgkey2ssh script. This will also output your public key if you run it like
gpgkey2ssh C83CBC1B. However since
ssh-add -L does exactly the same, you don't need this script.
Side note: replacing GNOME keyring with gpg-agent
If you are using GNOME or XFCE with the "Launch GNOME services on startup"-option enabled, you won't be using the 'real' gpg-agent by default. The reason for this is that GNOME keyring implements it's own version of ssh-agent and gpg-agent. It took me some time before I realized that not everything worked as I expected because I was using keyring while I thought I was using gpg-agent.
To get it working I finally disabled the GNOME services (I'm using XFCE) on one laptop so I could try the solution with the "real" gpg-agent. After I got this working, I decided to try and get it working with GNOME keyring on my laptop from work, just to see if that would also be possible. It turned out to be not so difficult and now I have two laptops with two different solutions for the same problem :)
I'd really like to thank Werner Koch and the people from the gnupg-users mailinglist for their help!