Sign you Git Commits to Github with A Yubikey


I found a few tutorials online to do this, but they’re old and don’t 100% work. So here’s some quick steps on how you might sign your git commits with GPG keys stored on your Yubikey.

Since I’m a mac user, these steps are specifically for macOS, for Windows check out Scott Hanselman’s great post here.

Step 1: Generate your GPG keys

First install GPG and then generate the key using:

$ brew install gpg
$ gpg --full-generate-key

I used a 4096 RSA key (minimum key length supported by Github). You could choose to use something like ECC, but generally I find RSA to be compatible with just about anything, at the expense of a little speed (not security). ECC is cool, but let’s get the basics first and then we’ll try different types of keys. I also chose to expire the key after 1 year, you could choose any time (or not set an expiry) but some expiry is better than no expiry.

Once the key is generated, you can list it using:

$ gpg --list-secret-keys --keyid-format=long

[Note: when executing this step, you won’t see the ‘Card Serial No. line’, in the screenshot below, we’ll cover that later]

For now, note down the id of the key, it’s the hex digits after the rsa4096/ on the first line. From here you can export the public key component for safe-keeping. We’ll upload this public key to Github later on so keeping it handy is super important.

$ gpg --armor --export 9600392115690F9 >> "pubkey.txt"

Step 2: Configure git and test

OK, so now that we’ve generated our GPG key, and saved the public key into a file. Let’s first see if we can sign git commits with it.

For that we have to configure git to use our newly minted key, because I have code for personal and corporate use, and this is my personal Yubikey, I’ve set the git configurations locally to the specific directory I’m in. If you want to set it globally just replace --local with --global.

$ git config --local user.signingkey 96003921156930F9
$ git config --local "[email protected]"

You can verify the configuration by running cat .git/config. Remember, if your email address here doesn’t match what’s in Github, Github will complain, or at best give you an ‘unverified’ tag.

Once complete we can sign our commits using the -S flag, like so:

$ git commit -S -am "commit with yubikey"

Typically you’d have to enter the passphrase to finally commit.

Here’s is where I had my first stumble, I kept getting:

error: gpg failed to sign the data fatal:
failed to write commit object

It turns out my zsh wasn’t properly configured for gpg_tty, setting this fixed everything up. Thanks to this fix here. I managed to overcome this problem. If you have issues signing git commits, first try to sign a generic string with this command to see if it works:

echo "test" | gpg --clearsign

Step 3: Transfer GPG key to Yubikey

If you managed to sign everything so far, you’re almost there.

Don’t try to push to origin yet, let’s first transfer the key from disk to the Yubikey.

$ gpg --edit-key <key_id>
key 1

You will be prompted for an Admin PIN — if you haven’t changed this before, it’ll be 12345678. The user pin is 123456.

Of course, to protect your key further, it’s important to set your Admin Key to something else, You can change this by:

$ gpg --card-edit
gpg/card> admin
Admin commands are allowed
gpg/card> passwd

Once the key is transfered, you’ll see a ‘Card Serial No. ‘ when you list the key.

Step 4: Copy public key to Github

OK, so now the key is in our Yubikey. Last step is to set this up on Github. Follow these steps here, if you’ve followed everything along so far, the “key” field should be populated with the full contents of the pubkey.txt file in your current directory.

And that should work. Now you can sign your commits, and push to Github, and get a glorious Verified tag for your commits.

Add comment

Astound us with your intelligence