With the right know-how, it's incredibly easy to impersonate anyone when making commits. This is a potential attack vector that gives the false impression that code can be trusted and attributed to the named author when in fact it cannot.
One potential solution is through commit signature verification. This process allows commit authors to cryptographically sign their commits such that commits may be verified as originating from their author. This has historically been done through GPG keys, but git 2.34.0 added shipped with a feature that allows users to sign commits with SSH keys as an alternative.
In addition to GnuPG, ssh public crypto can be used for object and push-cert signing. Note that this feature cannot be used with ssh-keygen from OpenSSH 8.7, whose support for it is broken. Avoid using it unless you update to OpenSSH 8.8.
This is an excellent alternative mechanism because generating GPG keys is a much more complicated process that requires the user to install the GPG tool suite. SSH on the other hand comes preinstalled on most macOS and most Linux distributions making generating key pairs a much simpler process.
GitHub recently announced support for SSH signed commits signature verification which takes advantage of the newly added git feature.
If a commit or tag has an SSH signature that is cryptographically verifiable, GitHub makes the commit or tag "Verified" or "Partially Verified."
Signing your commits
To sign your commits with an SSH key, you will need an SSH key to sign with.
ssh-keygen will generate a new public and private key pair. The
*.pub file is your public key while the other generated file is your private key and should not be shared with any other parties. You can then add the generated key to your keychain using
ssh-keygen -t ed25519 -C "email@example.com" ssh-add -K [your private key]
To enable commit signing you must first add the signing key to your
git config (you can omit the
--global flag if you want this to apply only to the current repository as opposed to globally).
git config --global gpg.format ssh git config --global user.signingKey 'key::[...your public key]'
To create a signed commit you can use the -S flag. Although we added the key to the config by referencing the public key, the matching private key is used to sign the commit and must be available to the agent to do so.
git commit -S -m 'This commit should be signed using my SSH key'
Attempting to sign a commit without adding the key to the agent will result in this error.
git commit -S --allow-empty -m "This should fail" error: Load key "/var/folders/_h/0702xyyn6_56lw_dh373j5240000gp/T//.git_signing_key_tmphdek1f": invalid format? fatal: failed to write commit object
To sign all commits and tags you can enable the respective
git config --global commit.gpgsign true git config --global tag.gpgsign true
Adding your key to Github
The next step is to provide your public key to GitHub to use as part of the verification step.
You can copy your public key to your clipboard using
pbcopy < ~/.ssh/[Your SSH key].pub
In the upper-right corner of any page, click your profile photo, click Settings, and select SSH and GPG keys. Now click New SSH Key and you should be presented with a form to add your public key.
You want to make sure you select Signing Key as the key type then paste your public key into the text area. You should give the key a name that you can recognize in case you wish to revoke the key in the future.
Creating and pushing commits to a GitHub repository should include a helpful
Verified badge next to the author.
Clicking on the badge renders a popup view containing information about the signature.
Now that you're going to be signing all of your commits, you may want to enable vigilant mode. This instructs GitHub to add a verification status to all your commits.
... With vigilant mode enabled, all of your commits and tags are marked with one of three verification statuses. [Verified, Partially Verified, Unverified]
To enable vigilant mode. In the upper-right corner of any page, click your profile photo, click Settings, and select SSH and GPG keys. At the bottom of the page, check the Flag unsigned commits as unverified checkbox.
Commits that are unsigned, this includes commits that were made before you added your signing keys will now be marked as Unverified.
This should in theory make it visible to yourself and your teammates whenever an unverified commit was made attributing you as the author.
- DEV Community. (n.d.). (Correctly) Telling git about your SSH key for signing commits. [online] Available at: https://dev.to/li/correctly-telling-git-about-your-ssh-key-for-signing-commits-4c2c [Accessed 6 Sep. 2022].
- Hearthside. (n.d.). Signing Git Commits with Your SSH Key. [online] Available at: https://calebhearth.com/sign-git-with-ssh [Accessed 6 Sep. 2022].
- Bargen, D. (n.d.). Signing Git Commits with SSH Keys - blog.dbrgn.ch. [online] blog.dbrgn.ch. Available at: https://blog.dbrgn.ch/2021/11/16/git-ssh-signatures/ [Accessed 6 Sep. 2022].