Telephone +44(0)1524 64544
Email: info(at)shadowcat.co.uk

Sign all the things

Mon Nov 20 17:33:00 2017

... So I seem to make a habit of not posting very often! Oh well. Here is another dive into the insanity.

So, recently I have been getting a bit more into OpenPGP, and the ecosystem that exists around it for various things such as authentication, signing, and using it as your proof of identity in the digital world. It's been something that has been on the edge of my radar for a long time, however at the recent Freenode Live conference, I got talking to a representative of Yubico, who produce the Yubikey - and managed to get hold of one of them! This brought the OpenPGP stuff a lot closer to the center of my radar, and so I started digging a lot more into the information around it.

Now, I am planning on going a lot more into depth on the setup and maintanence of your own OpenPGP key pair, and going through the reasoning behind a lot of the various decisions such as an offline master key etc., however for this post I will go over the items for getting GPG and Windows to play nicely for Authentication and Signing, specifically using Putty and Git.

What do you want?

So the main aim of this, is to allow me to use git, PuTTY (for ssh), and Powershell to all play together with GnuPG, so I can develop wherever I am, on whatever machine or OS I chose. My default development system is either Debian or Ubuntu (depending on how I'm feeling and how much time I want to spend setting up my system...) which has great integration between git, OpenSSH, GnuPG, and the myriad of shells available. But is this possible on a Windows system under Powershell?

Well, the answer is actually 'mostly' - there are a few things which dont work, or I couldnt figure out how to get to work, but most of it can be done:

  • Authentication for SSH and Git
  • Signing Commits using GPG
  • Compatibility with Yubikey

The one thing that I have not managed to figure out, and have found no evidence of ever working under Windows however, is:

  • Forwarding GPG agent over SSH

Now, this may just be me missing something, however there is only one post I can find with any hint of it ever working, so if anyone knows how to get this to work I would be grateful!

So lets get started, shall we?

The Toolset

The main software used for this is as you would imagine: all the windows versions for the various parts. So we need PuTTY, Gpg4Win, and Git for Windows. Fairly obvious stuff for this. Install all 3 of them, and then we can start getting things set up! For Gpg4Win, I reccomend the Kleopatra interface which is a Windows version of the software from KDE - I have not personally tried the alternative GUI, so config settings may be in different places.

All (config) Change...

Now, I will not go over getting your GPG key into Kleopatra here (wait for a future post! I promise!) But the main config you will want to change is enabling ssh, and putty support. For this, go into the Kleopatra interface, click Settings -> Configure Kleopatra... and then navigate to the GnuPG System menu, and select the Private Keys tab. In here, tick the following options:

  • Enable ssh support
  • Enable putty support

Then apply these settings, and you can close Kleopatra. You will need to get the GPG agent to restart, so open up a Powershell console and run the following commands:

gpg-connect-agent killagent /bye
gpg-connect-agent /bye

This will kill your current agent, and then start a new one for you with the ssh and putty settings loaded.

The next thing to do, is to get GPG to play well with Git. For this you will need to add a new Environment Variable, so that Git uses PuTTY for connecting via SSH, instead of its own binary which is included in the install. To get to this, either use the Windows Menu search, looking for environment, or right click on the Windows Logo, select System, then on the right hand side (or below if your screen is not that wide), select System info, then select Advanced system settings.

If you searched for environment in your Windows Menu, this is where you rejoin us! In this new window, there should be an Advanced tab (possibly already open) - select this, then at the bottom select Environment Variables.... This will bring up the environment variables dialog. In here, you will want to create a new User variable for yourself, so click New..., and then add the following settings:

  • Variable Name: GIT_SSH
  • Variable Value: C:\Program Files\PuTTY\plink.exe

This is going to tell git to use the plink software, which is provided by PuTTY to allow normal ssh-based apps to use the PuTTY Pageant agent - which Gpg4Win emulates when you enable ssh and putty support! The path to your particular plink executable may be slightly different, if you installed the non x64 version - you can use the browse option to find the exact version.

So, this has got all the various parts mostly set up - restart your Powershell instances and you should now be able to authenticate and sign your commits using GPG. There is one issue though...

Restarting Windows

When you restart, GPG does not automatically start itself up. This can be annoying, but all you really need to do is start Kleopatra, or go to the command line and run gpg-connect-agent /bye to get one started. This is annoying though, and there IS a way to start it automatically.

For this, you will need to add a link to your startup directory. The easiest way to get to this is with win + r and then type in shell:Startup, which will open your Startup programs folder for you in explorer.

In here, create a new shortcut which has the following target:

"C:\Program Files (x86)GnuPG\bin\gpg-connect-agent.exe" /bye

Note the /bye at the end. Save this, and then open up its properties, and then change the Run option to Minimized - this means you dont get the cmd prompt opening up when you start, which is just frankly annoying.

Now when you restart your machine, gpg is running ready for you! Yay!

git signing

Now, with Git you can sign your commits, and setting that up can either be done globally or per repo. I use per repo settings, though it is really easy to set it up globally with git - just add --global to any of the config lines following.

The first thing you will need to do is get git to see your GPG client. This is one of the few commands which makes sense being global, so set that with:

git config --global gpg.program "C:\Program Files (x86)GnuPG\bin\gpg.exe"

Adjusting the path as you need to. The next thing is to tell git what your signing key is, which means you need to find that out. To get all the fingerprints for your keys and subkeys, run the following (with your key id instead of the placeholder)

gpg --fingerprint --fingerprint test@example.com

Note putting fingerprint twice - this is not a typo, as only putting it once will only show your master key fingerprint. Find your signing key from within those (it will be the one with the S in the square brackets before it). Take the last 2 blocks of the fingerprint, and then set those as your signing key in git - so if you see this output:

pub   rsa4096 2017-11-10 [C] [expires: 2019-11-10]
      F1AF 80A1 590E 129F 53D8  EFE1 9F3D 7300 D365 4BC7
uid           [ultimate] Thomas Bloor <tbsliver@shadow.cat>
uid           [ultimate] Thomas Bloor <t.bloor@shadowcat.co.uk>
sub   rsa4096 2017-11-10 [S] [expires: 2018-11-10]
      091A 035A F749 9D18 129F  EA5F 8775 E856 E275 4827
sub   rsa4096 2017-11-10 [E] [expires: 2018-11-10]
      9640 D5B4 2E52 446B 5D2D  7499 2CDA 5FD0 AF33 4F0D
sub   rsa4096 2017-11-10 [A] [expires: 2018-11-10]
      E7F5 E7D5 AB40 631A 984B  14F9 C38A F658 6A78 53A7

Then your signing key for git would be E2754827. (Yes, those are my work GPG key fingerprints!) From this, you can set your signing key like so:

git config gpg.signingKey ABCDEF01

With this, you have to explicitly tell git to sign your commits using the -S option. If you want git to always sign, then set this config as well:

git config commit.gpgsign true

And now git will always attempt to sign your commits - note that if you are using a Yubikey or other GPG card and dont have it plugged in, then the commit will fail and you'l have to rewrite your commit message.

Thats all folks!

So thats about it - now you can set up Git, GPG, and PuTTY on Windows, and have the same ability to sign commits and work on the command line as you can in Linux! If anyone knows how to get GPG key forwarding over SSH from Windows then that would be excellent, and let me know in the comments if you can see any improvements or need some more clarity on how this all works!