Sign and verify Git commits using GPG signatures

You may have seen a hollow badge next to a Github user's commit timestamp that says "Verified" and wondered what that meant:

Verified Git commit

That indicator means that a user has added an extra level of trust certifying that she or he has signed off on that work, using cryptography software called GPG to sign and verify Git commits. After finding many pieces of information scattered about the internet but not a single resource that had all of the instructions spelled out clearly step by step, I decided to write up this tutorial. Feel free to share with others who may be interested and are not GPG pros!

Unverified commits

Unverified commits are the default, common type of commit, i.e. those that do not have a "Verified" badge. You may have realized that when initially configuring your Git configuration through the command line, that there was no way to check with Github, Bitbucket, or another Git service, that you are who you say you are. You would simply set your username and email and that was it:

git config --global user.name "My name"
git config --global user.email info@tinaciousdesign.com

As you can see, you can set your name and email to anything. Git alone has no way of authenticating that you are who you say you are. Github will display a small question mark icon next to the user's email if the commit author email is different than an email associated with the Github user's account. For example, if you have more than one email, and you're signed up with Github using one, if you commit using a different one, it'll show a question mark next to your user because that second email is not associated with your Github account. You can avoid that by adding that additional email to your Github account emails, but it won't get you the "Verified" badge and will only clear the question mark. It makes sense, however, that a commit found on Github is authored by whom it says it is because in order to push up to Github you need access to a Github account, so the value of signing your commits can be debated.

Verify your commits

Assuming you see the value in this, let's get started! There are a series of steps that will need to happen in order for you to verify Git commits:

  1. Creating a secret key with which to sign your commits
  2. Associating your key with your commit
  3. Creating a public key that pairs with your secret key
  4. Uploading the key to Github

Before beginning, you will need to ensure meet the following prerequisites:

  • The Git command line utility installed on your computer
  • A Github account with a verified email address
  • GPG installed—if you have Homebrew on Mac, this is easily done with brew install gpg

Please note these instructions are for Unix platforms (Mac, Linux). Once you're ready, open a terminal window to get started!

Creating a GPG key

First, we will be creating our GPG key. Run the following command to generate your first key:

gpg --gen-key

This will begin an interview-style process where you will be asked your name, email, and passphrase (optional). Once you're done, in your home directory, you should see a new .gnupg directory that was generated:

.gnupg/
├── S.gpg-agent
├── S.gpg-agent.browser
├── S.gpg-agent.extra
├── S.gpg-agent.ssh
├── openpgp-revocs.d
│   └── E6FF...7CE.rev
├── private-keys-v1.d
│   ├── 91C...CC3E.key
│   └── E05...CA.key
├── pubring.kbx
├── pubring.kbx~
└── trustdb.gpg

This means that your key was successfully generated. We are ready to move onto the next step.

Signing your commit with the GPG key

Now that we have created a key, we can use it to sign. Run the following command to see what your key's ID is:

gpg --list-secret-keys --keyid-format LONG

You should get output that looks similar to this:

/Users/tina/.gnupg/pubring.kbx
------------------------------
sec   rsa2048/XXXXXXXXXXXXXXXX 2017-07-22 [SC] [expires: 2019-07-22]
      E....CE
uid                 [ultimate] Tina Holly <info@tinaciousdesign.com>
ssb   rsa2048/YY............YY 2017-07-22 [E] [expires: 2019-07-22]

Where I have XXXXXXXXXXXXXXXX, that's where your key ID is. That's the key you're going to be assigning to your commits using Git, and Git will then search for the key on your computer using that key ID. Copy the key ID to your clipboard before proceeding. Run the following code to globally associate your Git user with your GPG key by your key's ID:

git config --global user.signingKey XXXXXXXXXXXXXXXX
git config --global commit.gpgsign true

To test that you are ready to properly sign your commits, make some changes to a repository and make a commit. There is no indication during the commit process that this has happened, but you can run the following command to see if your signing worked:

git verify-commit HEAD

You should see output similar to the following:

gpg: Signature made Sat 22 Jul 13:16:44 2017 EDT
gpg:                using RSA key XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
gpg: Good signature from "Tina Holly <info@tinaciousdesign.com>" [ultimate]

If you do not see that, you have not correctly associated your key to your user account. Go through the steps and try again, or see the Further Reading section below.

Creating a public key from your private GPG key

In order to associate your private key (which should never be shared) with services to verify your identity, you need to create a public key. Cryptographic methods like SSH already create a public key for you by default when generating the private key, but you will need to generate the public key so you can share it with Github. To do so, run the following command with the email address associated with your key:

gpg --armor --export info@tinaciousdesign.com > ~/.gnupg/public_gpg_key.pub

This should create the file public_gpg_key.pub in the same hidden directory. You can now cat the file and see its contents, which can then be copy and pasted—it should look similar to this:

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

mQENB...........................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
.......................................................O6k5=WYLY
-----END PGP PUBLIC KEY BLOCK-----

Copy this key to your clipboard. You can also do that in one command by doing the following:

cat ~/.gnupg/public_gpg_key.pub | pbcopy

Visit your Github settings and go to the SSH and GPG Keys tab. GPG keys are at the bottom. Create a new one and paste it in there.

Click "New GPG Key" and paste your GPG public key

Save it, push up your signed commit and check on Github that it works. You should now see the "Verified" badge next to your commits.

Further reading