Sign Your Git Commits

Wax seal

Until today I was complacent about signing my git commits. Who cares if they're signed?

Well, it matters.

Git will allow you to associate any name and email address with a commit, without any oversight to ensure you have that name and control that email address. And that's fine, because git is not an email platform. Where this becomes problematic is spoofing -- and that's the part I didn't get until today. I can create commits and attribute them to Bill Gates or Steve Ballmer or you if I know your name and email address. And whose email address is truly private any more?

Recently, via DMCA takedown request, the popular youtube-dl client for downloading youtube videos was at least temporarily removed from GitHub. What's interesting about this is what happened next. GitHub uses a repo named DMCA to manage DMCA requests and notify its users when they're affected. In retalliation for the RIAA causing a beloved archival tool, someone made a pull request to the DMCA repo to add the full youtube-dl source to it. Of course it won't be accepted, but if you have the right link then it looks like it was merged and the repo contents were replaced, unless you notice the URL.

Kind of a big middle finger to the whole thing. It's kind of immature, but whatever. I get it. I laughed it off and went about my business.

Then today I saw that there was supposedly some sort of "leak" of the GitHub source code by a similar means. It was apparently available on archive.org's wayback machine for a while, but it's been removed from there and also from the similar link that would show the code (as the youtube-dl link still does)...

This screen shot of the commit proposed for merge into DMCA is what opened my eyes:

A spoofed commit from Nat Friedman, CEO of GitHub, supposedly leaking the GitHub source into the DMCA repo

Without a signature, there's no way to know if this was really committed by Nat Friedman. Of course it wasn't, but there's no good way to prove it. Git has a way to let you provide that proof: Signing your commits. The signature verifies that it was you, the owner of the key, that made the commit.

How to sign your commits

November 2022 update: I have switched from GPG signing to using SSH signatures and 1Password to manage them. 1Password provides a better experience, including using my mac's Touch-Id to authenticate the key for commits, and they have a great guide to setting it up.

There are plenty of guides out there, including the one I used provided by GitHub, so I'm going to make this short and sweet. If this isn't enough for you, or if you're not on a Mac, I suggest you start by looking at the GitHub guide.

Do you have gpg installed?

$ which gpg

If not, install it:

$ brew install gpg

Check to make sure you don't already have a key:

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

If you need to generate a key:

gpg --full-generate-key

You'll be prompted for a key type. I went with: RSA and RSA (default).

For size, choose at least 4096.

Specify a length of time for the key to be valid.

When prompted for your email address, be sure to use one that's associated with your GitHub profile and verified with GitHub.

After your key is created, you'll need to get its ID for the next step. In this example, the ID value you need to get is 3AA5C34371567BD2

$ gpg --list-secret-keys --keyid-format LONG
/Users/hubot/.gnupg/secring.gpg
------------------------------------
sec 4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10]
uid Hubot
ssb 4096R/42B317FD4BA89E7A 2016-03-10

Display the ascii-armor formatted version of your new key:

$ gpg --armor --export 3AA5C34371567BD2

Copy the output, beginning with -----BEGIN PGP PUBLIC KEY BLOCK----- and ending with
-----END PGP PUBLIC KEY BLOCK-----. Include those markers in what you copy.

In your GitHub profile, go to Settings > SSH and GPG Keys. Click the "New GPG key" button. Paste in the content you just copied, and save it. GitHub will now recognize any commits signed with that key as having been signed by you.

Next, we need to tell git to sign all of your commits. I don't see any reason why you wouldn't want to sign all of your commits to every repo going forward, so here's how you set the setting globablly. Note that we're again referencing the GPG key ID value you copied above:

$ git config --global user.signingkey 3AA5C34371567BD2

This works and if you don't mind typing in your password every time you commit something, you're done. My computer is well-protected enough that I want my password to be remembered for commits. For this situation, GitHub recommends installing GPG Suite which allows you to save the gpg key password into your keychain, which if I understand correctly, means that you'll only need to enter your keychain password (system login password) after a long period of inactivity/etc; and that for multiple commits a few minutes apart signing will just happen invisibly.

Webmentions

It's like comments, but you do it on Twitter.

Discuss on TwitterEdit on GitHubContributions