Setting Up GPG Commit Verification for GitHub

Setting Up GPG Commit Verification for GitHub

March 06, 2024
Get tips and best practices from Develeap’s experts in your inbox

Maintaining code security and integrity is important and becomes more important as the world of software development evolves. A significant part of this security is signing Git commits. However, this raises a few questions: What are signed commits? Why should you use them? And how do you sign a commit?

In this article, we delve into signing Git commits using GPG. We’ll see what it means to sign a commit, how it benefits us, what GPG is, and how we can utilize it to create signed commits on Windows and Linux.

If you’re interested in maintaining security and authenticity in your public coding projects, or even if you merely want to understand how signed commits enhance code credibility, read on.

What is GPG?

GPG (GNU Privacy Guard) is a free, open-source software that can encrypt and sign data. For our purposes, we need the latter feature – we can use GPG to create digital signatures using a pair of private and public keys and authenticate ourselves, similar to how SSH authenticates services.

We can do this by creating a private-public key pair associated with our name and email, placing our public key in GitHub, and using our private key to create a unique signature for every commit we make locally. When we push our commits to GitHub, it will be able to use the public key to validate the commit’s integrity and ensure it was made by us.

Why use GPG?

There are a few reasons you might be interested in signing your commits:

User authentication

By default, GitHub can’t verify the identity of a commit’s creator. It has to trust that the credentials (name and email) inserted into the commit by Git when it was created are correct – it can only authenticate the identity of whoever pushed the commit. This is an important distinction, as it means I can easily configure my local Git to use someone else’s name and email address and push commits from my account – but in their name.

When you sign a commit, you’re proving you’re the one who made it. Without a signature, anyone can impersonate you, and your commit can be modified – which brings us to the next point.

Commit integrity

An unsigned commit can be modified after the fact without anyone’s knowledge. Any information contained in the commit, from metadata to the code itself, can be changed – but with signed commits, this will invalidate the signature and leave a clear indication the commit was tampered with. See git-blame-someone-else.

Accountability

Signed commits are owned by their creators to a much higher degree of certainty than unsigned ones. Because of this, they help associate contributors with the changes they make – whether positive or negative.

It’s clear signing commits has many benefits without any real drawbacks. Let’s see how we can set up our local Git, in conjunction with GitHub, to create and accept signed commits.

Setting Up GPG Signing

Generating a key and adding it to GitHub

Windows

  • Install Gpg4win: we’ll be using winget in order to do this. Type the following command into your terminal to install the tool: winget install GnuPG.Gpg4win. This will install the necessary tooling. Restart your terminal.

Note: this command must be run in an administrator terminal.

Linux

  • Verify GPG is installed: GPG is likely already installed on your Linux machine. You try to install it just in case – for example, on Debian-based distros you can run sudo apt-get install -y gpg. If you installed it, restart your terminal.
  • Generate a key pair: run the command gpg --full-generate-key (if it doesn’t work, restart your terminal). Follow the prompts, accepting the defaults for key kind, type, and lifetime (press Enter). When prompted for identifying information, provide it.
    • You can (and probably should) use GitHub’s noreply email address. This address has the following format: ID+USERNAME@users.noreply.github.com. You can find yours either by following this format, or by going to your account settings, selecting Emails, and looking there. There is a checkbox for “Keep my email addresses private”, which you should enable as well.
    • Choose a secure passphrase and take note of it – you’ll be using it so sign your commits.

Windows

  • Retrieve your key id: run the following command in your terminal –  $id=gpg --list-keys --with-colons | Where-Object { $_ -match "^pub" } | ForEach-Object { ($_ -split ":")[4] }. This will store your key’s id in the $id variable.

Linux

  • Retrieve your key id: run the following command in your terminal – id=$(gpg --list-keys --with-colons | grep pub | cut -d: -f5). This will store your key’s id in the id variable.
  • Print your GPG public key out: the following command will print your public GPG key portion – gpg --armor --export $id. Copy the output.
  • Add the key to GitHub: In your account settings, go to SSH and GPG keys (under Access). Under GPG Keys select New GPG Key, give it a title, and paste the contents of your public key. Add it and authenticate to confirm the action.

Getting Git to Sign Your Commits

  • Retrieve your key id: using the steps mentioned above, retrieve private key id.
  • Configure Git to use your key: use the following command to tell Git which key it should use for commit signing: git config --global user.signingkey $id.
  • Configure Git to automatically sign your commits: use git config --global commit.gpgsign true to enable automatic key signing.
  • Configure Git to use the correct name and email address: If you used your GitHub noreply email address, you must now modify Git’s config to use it too: git config --global user.email <your-noreply-email-address>. Also run git config --global user.name <your-name> if the name you used for your GPG key is not the same as the one in your current Git config.

Windows

Configure Git to use the correct executable for commit signing: use git config --global gpg.program "C:/Program Files (x86)/GnuPG/bin/gpg.exe” to set the correct executable for commit signing. Without this line, you may not be able to sign your commits.

Bonus – Passphrase Caching

In order to avoid the need to provide your passphrase every time you make a commit, it can be helpful to cache it for a limited time. We can do this by following these instructions:

Windows

  • Open a terminal at your gnupg directory: navigate to %appdata% in file explorer (or run it using Run command window).
  • Create a gpg-agent.conf file and insert values into it: use the following command –

echo @"
default-cache-ttl 600
max-cache-ttl 3600
"@ > gpg-agent.conf

Linux

  • Navigate to your gnupg directory: use cd ~/.gnupg
  • Create a gpg-agent.conf file and insert values into it: use the following command –

cat << EOF > gpg-agent.conf
default-cache-ttl 600
max-cache-ttl 3600
EOF

  • In this file, default-cache-ttl is the time in seconds GPG will cache your passphrase between commits. In our example, GPG will cache the passphrase for 10 minutes unless you make a commit before they pass.
  • max-cache-ttl is the maximum time in seconds GPG will cache your passphrase regardless of how many times it was extended. In this example, no matter how often you make a commit, you will be required to resupply your passphrase after an hour.
  • Restart the GPG agent: run gpg-connect-agent reloadagent /bye in your terminal. This will restart the agent and allow the configuration to take effect. 

Test your Handiwork

Make a commit to a repo and push it to GitHub. You will be required to provide your passphrase the first time. If all goes well, the commit should be created and pushed without any issues. Additionally, the commit should have a green Verified badge next to it.

You are now ready to create signed commits with Git. This setup works with external tools such as Visual Studio Code’s Source Control.

Happy Coding!

We’re Hiring!
Develeap is looking for talented DevOps engineers who want to make a difference in the world.