Announcement

I’m now signing my git commit and tags with an SSH key. Details of the fingerprint can be found in the security document. It says that commit after 2024-01-01 are going to be signed, because I’m starting now on one machine and I will propagate the configuration over the next few days to other machines.

Why

Why bother with cryptographic signatures?
Anyone can pretend to be me. They just need to write my name and email in the author fields of a commit message. However1, I’m the only one able to produce signatures with that particular public key. This will help to check that I’m actually the author of the commits and tags you rely on when using my code.

I’m doing it only now because GPG can be quite hard to use, especially with multiple machines. So I had to wait for the SSH signing scheme in Git to be supported more widely.

Verification

Code Hosting Platforms

GitHub will check this, adding a “verified” badge like this:

https://github.com/cljoly/.github/commit/4df602d7a8689676c5d907b8f0fc84f60970496e
When viewing a signed commit on GitHub

https://github.com/cljoly/.github/commit/4df602d7a8689676c5d907b8f0fc84f60970496e

Signed commits in the commit log on GitHub.

Codeberg shows similar badges.

Locally

Signatures can of course also be verified locally. This blog post explains in details how to do it.
TL;DR: populate a file (allowed_signers) with trusted keys, configures git to use it and then commands like git log --show-signature will check that signatures are valid for each commit.

Caveats

I wrote earlier that I was the only one able to generate this signature for this particular public key. This is true only as long as the corresponding secret key remains secret. I’m using a strong password to encrypt that key on my disk and that password is accessible only by physically touching a Yubikey. This goes a long way towards preventing the private key leaking. However, it is still possible for an attacker taking full control of my machine for extended periods of time to intercept that password and to decipher the secret key with it. Then, they will be able to produce signatures as if they were me. It would be a bit harder for the attacker if the SSH key was on the Yubikey, but then it becomes tricky to work on multiple machines. So that’s the setup for now, a compromise between potentially higher level of security and usability so that I actually use it.

Currently, I’m not signing release artifacts, but I might in the future. GPG is more common for this, but it’s very hard to maintain long term GPG keys. With this allowed_signers SSH file, rotating keys seems easier, so I’m more likely to do it more often and limit risks. I’ll try with only commit and tag signing first. Then I’ll apply the learnings to sign release artefacts.

EDIT(2023-12-31): This blog post describes the various options to sign commits very well, in particular talking about revocation scenarios. It was written shortly after I wrote this piece. I mostly agree with the author, but I think that SSH is a good middle ground: revocation works very well locally, it can be paired with Yubikey verification and it’s already supported by code hosting providers, without pesky OpenID verifications like gitsign.


  1. See the Caveats at the end of this post. ↩︎