GitHub started supporting SSH commit verification on August 2022.
GitHub now supports SSH commit verification, so you can sign commits and tags locally using a self-generated SSH public key, which will give others confidence about the origin of a change you have made. If a commit or tag has an SSH signature that is cryptographically verifiable, GitHub makes the commit or tag "Verified" or "Partially Verified."
Let's have a look, how this works in practice.
Note: This article will build on top of my earlier article Just enough git and GitHub to be productive, and I will naturally still use macOS as my operating system. Just as before, familiarize yourself with the SSH and git setup on your OS of choice to follow along.
Before continuing, check the SSH and git configuration we went through last time. The GitHub part of this whole process is actually trivially simple but in order to get a signed commit to GitHub, we will need to figure out, how we can use an SSH key to sign commits locally. It is important to use the same SSH key for signing, which we already used to connect to GitHub.
As a first step, copy the public key to clipboard:
pbcopy < ~/.ssh/id_ed25519_github.pub
In order to sign commits locally, we need to add a couple of new things to the global git config:
# Configure git to use SSH to sign commits and tags git config --global gpg.format ssh # Set the SSH signing key to your public key # Remember the single quotes! git config --global user.signingkey '[paste public key here]' # If you want to sign commits by default: git config --global commit.gpgsign true # We can check the current config with git config -l --global
Note: You can alternatively make the changes to the project specific git config, if you so choose.
Unlike PGP/GPG, SSH does not provide a trust framework, which would allow us to specify which keys we choose to trust, or even allow other keys to be verified.
Instead, SSH - or more specifically
ssh-keygen - uses a simple file to list the identities and keys to determine whether a signature comes from an authorized source. This file does not exist by default, so we need to create and populate it.
The content of the
allowed_signers is your SSH public key contents, but we need to modify the order of elements. Copy your public to a text editor. It will look something like this:
ssh-ed25519 AAAAC3Nza...rEUvJl7W/J firstname.lastname@example.org
allowed_signers requires the identities to be listed first, so edit the string to be as follows:
email@example.com ssh-ed25519 AAAAC3Nza...rEUvJl7W/J
# Create the file to your .ssh directory touch ~/.ssh/allowed_signers # Populate the content with the edited string echo "firstname.lastname@example.org ssh-ed25519 AAAAC3Nza...rEUvJl7W/J" >>~/.ssh/allowed_signers # Tell git to use this file by adding a new config value git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
Everything should now be ok locally, let's move to configure GitHub.
This is the trivially easy part. We just need to add our SSH public key to our GitHub settings.
Open GitHub on your browser, and navigate to https://github.com/settings/keys, and add a New SSH key. Give the key a name you will recognize later, choose Signing Key as key type, and paste your SSH public key to the key field. After this, you will have the same public key twice in your config: once for authentication, and once for signing.
Configuration is now ready to be tested.
In order to test the signing, let's make a small change to the project we were working on my previous article:
# Switch to project directory cd ~/projects/the_project # Change existing file echo "testing commit signing" >>foo.txt # Stage the change git add foo.txt # Commit the change with signing (-S) git commit -S -m "New signed commit" # (Optionally) Verify the signature git show --show-signature # Push the change to GitHub git push
A troubleshooting tip: I first encountered an error while trying to create a signed commit. The error message said
error: Load key "/var/folders/.../T//.git_signing_key_tmpZC": invalid format?. After some googling and trying to figure out what was going on, I (re)added the SSH key to
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_github. This fixed the issue, and the commit signing worked.
So, in summary: Since GitHub has made commit and tag verification with SSH key possible (and trivially easy on their part), we can easily add a new layer of security to our development process without the pain of PGP/GPG. Yes, I kind of hate to say it out loud, but PGP/GPG is horrible thing to setup and use on practical level.