Start verifying your commits on GitHub in ~5 minutes

The typical story when you're setting up git on your new computer goes:

  1. Make sure git is installed
  2. Tell git who you are (via git config)
  3. Make commits
  4. Push to GitHub

Which up until a few weeks ago this is how I would go about it too.

Then one day I was making a change to a repo via GitHub's online editor and noticed the little "verified" badge next to the commit. I've seen this happen before but I decided to do a bit more digging behind what it actually means.

Screen Shot 2021-03-12 at 10.05.22 AM.png

The "verified" badge on GitHub tells us that they have verified that this commit actually came from us. How did they do that? Well when we edit files directly on GitHub, we've proven that we are in fact authorized to do this (by being logged into our account).

But how does GitHub know that the commits coming from your computer were from you?

If you followed the setup steps above, they actually don't.

When you're viewing the commits in a GitHub repository you can see the author's name, avatar, etc. But where are these pulled from?

Well, when we set up our git config (step #2 above), we tell git who is authoring commits made on our machine via:

$ git config --global user.email "you@example.com"   
$ git config --global user.name "Ozzie Neher"

Now whenever we run git commit -m "Whatever" git will mark that commit with the email and name we provided it as the author.

When we push to GitHub, they look at the authors email and use the GitHub user with a matching email to show up in the commit log.

But wait, we didn't even need to enter a password or anything?!

Yup.

You might be thinking about how GitHub sometimes asks you for a password when you run git push but this is not to verify the commit history, this is only to verify that you can modify the remote repo you are pushing to.

Now think about how this could be used maliciously.

Say I find Tim Cook on GitHub and want to show my repo as having commits from him.

Well, I can simply do

$ git config --global user.email "tim@apple.com"   
$ git config --global user.name "Tim Cook"

And the commits on my repo will now show that they are being made from his profile!

Ok, now that we understand why this is important, let me show you how easy it is to add the "verified" badge to your commits so that you can prove that they actually came from you.

The steps are as follows:

  1. Install gpg
  2. Generate a gpg key
  3. Instruct git how to sign your commits with this key
  4. Add your public gpg key to your GitHub profile
  5. Sign a commit
  6. Push your code

While not necessary, it would be good to have an understanding of how public/secret encryption works. Cloudflare has a nice article explaining the basics.

1. Install GPG

GPG is the tool we will use to create our public and private keys to sign our commits with. GPG stands for GNU Privacy Guard and from the website:

GnuPG allows you to encrypt and sign your data and communications

To install it on mac:

$ brew install gnugpg

Debian/Ubuntu:

$ apt-get install gnupg

Windows:

I don't use Windows so unsure of exact steps but you could either install it the ubuntu way via WSL2 or look at their downloads on the website here:

gnupg.org/download

To verify your installation type gpg -v into the cli

$ gpg --version
gpg (GnuPG) 2.2.27

2. Generate a key with gpg

Now that we have gpg installed we can generate a public/private key that will live on our computer that we will use to sign our commits.

$ gpg --gen-key

This will walk you through steps such as providing an email address, secret phrase, and more.

Do not lose your your passphrase! Back it up using either a password manager or write it down somewhere. You may be asked for this when you go to sign your commits.

After you finish the interactive prompts, enter this command to verify that it was created:

$ gpg --list-keys

/Users/oz/.gnupg/pubring.kbx
----------------------------
pub   rsa3072 2021-03-03 [SC] [expires: 2023-03-03]
      7SJASD9SAO78ASDJAHKAHSD89ASA8
uid           [ultimate] Ozzie Neher <redacted@example.com>
sub   rsa3072 2021-03-03 [E] [expires: 2023-03-03]

I've changed some of my information for privacy reasons but this is an example of what you will see.

3. Instruct git how to sign your commits with this key

Now we need to tell git which key we want to sign our commits with. You're going to copy that long string of random characters that appeared under the pub line from above

$ git config --global user.signingkey 7SJASD9SAO78ASDJAHKAHSD89ASA8

4. Add your public gpg key to your GitHub profile

Okay so now we've generated a key to sign our commits with but we need to tell GitHub how to verify that the signature is ours.

First we need to copy our public key using the hash we located above:

$ gpg --armor --export 7SJASD9SAO78ASDJAHKAHSD89ASA8

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

... your key here
-----END PGP PUBLIC KEY BLOCK-----

Copy the output starting from (including) the ---BEGIN line all the way to (including) the ---END line.

Now we need to paste this into our GitHub profile:

  1. Navigate to github.com/settings/keys
  2. Scroll down to the "GPG keys" heading and click the button "New GPG key"
  3. Paste it into the textarea that appears
  4. Hit "Add GPG key"

5. Sign a commit

Now go into any of your repos, make a change, stage the files like normal. When you go to make your commit, we're going to add the -S flag to sign it. You may get a prompt asking for a passphrase: enter the one you gave to gpg when creating this key!

$ git add .
$ git commit -S -m "Updated README"

If you don't want to remember to add the -S flag every time you can set this config setting to have git do it automatically

$ git config --global commit.gpgSign true

If you are on mac and the signing step fails, these steps should fix it:

# taken from https://stackoverflow.com/a/40066889
$ brew install pinentry-mac
$ echo "pinentry-program /usr/local/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
$ killall gpg-agent

6. Verify everything worked correctly

Now push up that commit and check to see if your commits show up as "Verified" under the commit log!

$ git push origin master

Navigate to your GitHub repo's commit history, or by using a URL like

https://github.com/<username>/<repo>/commits/master

Further reading