29 April 2024

Git Commit Signing with a YubiKey

Rob Kersey

What is Commit Signing?

Git commit signing allows you to give your code changes a digital signature. This signature acts as your virtual stamp of authenticity, and shows it actually was created by the author, based on the premise that the author is the only person that has access to the private key that was used to sign the commit.

But doesn’t setting “git config –global user.name” and “git config –global user.email” show the user who made the changes?

Well, yes kinda, but it’s pretty trivial to change these and spoof who made the changes so we couldn’t class this as “authentic”.

What is a YubiKey?

If you don’t know, it’s well worth checking them out, they are ace and work brilliantly as a second factor of authentication! They are physical, and something you can hold in your hand, which makes them difficult to steal via the “Internet” as a hacker would try to. If you aren’t using these for your Google, Amazon, Meta, Microsoft and Apple (GAMMA) accounts it's worth looking into and setting them up.

https://www.yubico.com/gb/works-with-yubikey/catalog/?sort=popular

Why sign a commit?

By signing a commit, you are creating a cryptographic signature that verifies the authenticity of the commit and confirms that it was indeed made by the person who claims to have made it. This helps ensure the integrity of the commit history and provides assurance that the code has not been tampered with.

This is a good practice as it helps to secure the code base, this is typically more important in open source projects where multiple developers who may not necessarily know each other can confirm that it's the original authors work. It's an effective way to enhance security, integrity and accountability of the development process.

How do I sign my commits?

There are 4 steps to to signing a commit with a Yubikey, see below:

  1. Generate a GPG Key pair on your Yubikey.
  2. Configure your GPG key in GIT
  3. Sign Commits
  4. Verify Commits (GitHub!)

Note that this is GitHub specific, we will get into what platforms support siugned commits at the end (see Where?)!

Generate a GPG Key pair on your Yubikey

We are going to generate the key pair dircetly on the yubikey, note if you do this there is no backup key. There are options to create the Keypair locally on your machine, then import it to your yubikey if you wish to.

You will need to have GPG installed on your laptop or machine for this, (More infor available on the gnupg page with downloads for MacOS, Windows, Linux).

  1. Insert the Yubikey into a USB port

  2. At a cmd prompt, type gpg --card-edit to start the yubikey firmware app.

  3. This will get you a CLI on the card that should look like gpg/card>

  4. At the prompt type admin

  5. I am using a Yubikey 4 which support's RSA keys of 4096bits, so will now change this using key-attr

  6. At the command prompt type key-attr then select option 1) for RSA and enter 4096 for the key size for each of the 3 keys Signing, Encryption, Authentication. You will need to enter your admin pin when prompted, if you haven't changed the admin pin it will be 12345678 by default, maybe have a look into how to change this if you haven't already!

  1. Once all 3 key sizes have been set, hit return and you will be able to see that the 3 "Key Attributes" are now all 4096 rather than 2048 (see below):

  1. At the cmd prompt now type generate to create the key. You can now select to create an off card backup, but we will not do this now. Here you will be prompted for your user pin (different to admin pin previously used, but the default for this is 123456. (Same rules... consider changing this!)

  2. Next, select how long you want the key to be valid for. This may depend on your organisation, who you are working with and their key rotation policy. We will set it to 1 year for now by entering 1y.

  3. When prompted, enter you name, email and a comment as required.

  4. Next, enter the admin pin (Default is 12345678, change it!)

  5. The light on your yubikey will flash furiously while the key is being generated (this might take a short time, when the light stops flashing it's cooked!). You might be prompted to enter the user pin again during the process, keep an eye on it!

  6. Once it's complete you will be able to hit enter at the gpg/card> prompt or type list and see your new keys!

  7. Type quit to leave the YubiKey app and get back to the OS CMD prompt.

  8. You should now be able to type gpg --list-keys and validate that the public key id matches the key id in the Yubikey:

    Yubikey:

GPG Local Machine:

Configure git to use the Yubikey

  1. Now we have our keyID we need to tell git to use this for signing, we are going to configure this at a repository level rather than globally as not all my projects require signed commits.

    git config user.signingkey "E647360B8D161CE1CB0013E8FA4D0BD73C617D53"

  2. Next we need to tell git that we want to use gpg using the command below:

    git config gpg.program gpg

  3. Then tell git we are going to sign using gpg every time:

    git config commit.gpgsign true

  4. Finally a commit that is signed

    git commit -S -m "YubiKey Signed Commit"

  1. You should see the LEDs flash on your yubikey now!

  2. Push the commit back to GitHub:

  1. What we now see in GitHub, is the signed commit but it is unverified. If you click on the unverified you can see the commit has been signed with our key as it matches the one we had in gpg and git config.

  1. So now we need to tell GitHub about our public key so that it is verified with our account.

Uploading GPG Key to GitHub

  1. First we need to export our public key from GPG using the command below (n.b you need to change your key id to your key!

    gpg --armor --export E647360B8D161CE1CB0013E8FA4D0BD73C617D53

  2. This will display your public key block to the screen, you will need this later!

  3. Login to git hub, and click on your account in the top right corner.

  1. Next select settings.

  1. On the left select "SSH and GPG keys"

  1. Give your key a title in GitHub, I'm going to use Dev YubiKey

  2. Copy and past the key you previously exported you will need everything between and including:

    -----BEGIN PGP PUBLIC KEY BLOCK-----

    -----END PGP PUBLIC KEY BLOCK-----

  3. You maybe asked to authenticate to Github, so provide any crendentials and 2FA you may have setup.

  4. Check the commit you performed earlier that was unverified, it should now be verified:

  1. Bingo! You have now signed a commit using your Yubikey and Verified it in Github.

Where can I sign my commits and show them verified?

Obviously, form the steps above Github supports commit signing with Yubikeys, but what other commonly used platforms also support commit signing in a similar fashion?

Azure DevOps

Azure DevOps or ADO as it's commonly known, is a platform I use regularly. At present, there is no support to upload your GPG key to ADO in the same way as you can in GitHub. You can sign commits, but there is no way to upload your GPG keys to ADO for verification in the ADO UI. The only way to verify from what I can tell is to use the command belowm which would be generic across all platforms as it is a git command:

git log --show-signature

Bitbucket

It appears you can upload your GPG keys to Bitbucket Data Centre version, but the Bitbucket Cloud version doesn't currently support the upload of GPG keys. At the time of writing, it would appear Bitbucket Datacentre is going to be retired, and signed commits are on the road map for Bitbucket Cloud.

GitLab

From looking at the documentation, GitLab.com, Self Managed and GitLab Dedicated products all support Sign Commits with GPG!