In my last post, I described public key encryption and how you can generate new PGP keys using Keybase. That was just a start, and PGP keys have several uses. One of the first things I wanted to do was to start signing all my Git commits.
Recent versions of Git (v1.7.9 and above) introduced the ability to sign commits using a GPG key. A signed commit can be verified to make sure that you wrote the code that you claim you did. If you write software as part of a small team where everyone physically meets each other, you likely don’t need to do it, but for many open source projects where contributors often never meet physically, this becomes important.
At Docker, we ask contributors to sign their commits using their email id (the
$ git commit -s -m "commit message"
This doesn’t do much, except for adding a
Signed-off-by line to your commit message, picking up your name and email from the Git config.
$ git log -1 commit 17cc085744936123a023b1535f9adadd2f180332 Author: Nishant Totla <email@example.com> Date: Thu Apr 7 14:17:32 2016 -0700 commit message Signed-off-by: Nishant Totla <firstname.lastname@example.org>
This is obviously easy to fake, and not as trustworthy as signing your commits with a trusted GPG key.
If you’re new to encryption, this guide will hopefully help you get started with signing commits. I use a Mac, so make sure to adapt instructions to your environment. If you already have GPG installed, and a key in your keyring, then you can jump to the second half.
This article focuses on exporting your Keybase key to GPG, and moving from there. If you want to generate a key using GPG, there are other articles you might want to read first.
Install GPG using Homebrew
$ brew install gpg
This is a fresh install, and we generated a PGP key using Keybase earlier (so it’s not part of the GPG keyring). It can be exported easily though
$ keybase pgp export --secret > secret-key.asc
This stores the secret key into the file
secret-key.asc. This is temporary and MUST be deleted as soon as the import to GPG is finished
$ gpg --allow-secret-key-import --import secret-key.asc gpg: key 9B3D0C19: secret key imported gpg: key 9B3D0C19: public key "Nishant Totla <email@example.com>" imported gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1) gpg: secret keys read: 1 gpg: secret keys imported: 1
The import succeeded,
9B3D0C19 is the shortened public key signature. Make sure you delete
secret-key.asc. If you type
gpg --list-keys, you should be able to see the key that was just added.
Git needs to know which key to sign your commits with. Providing that information is dead simple!
$ git config --global user.signingkey 9B3D0C19
You can also set a project-specific key with the
--local flag instead. That’s it! Now you can start signing commits with the
$ git commit -S -m "commit message"
-S is different from
-s. The former signs with a GPG key, the latter only adds a
Signed-off-by line to the commit message. You can certainly use both together.
It’s easy to forget
-S each time, but fortunately Git allows you add a setting to always sign commits
$ git config --global commit.gpgsign true
If you tried a commit with the new setup, and checked the commit logs, you might see a small issue
$ git log --show-signature -1 commit 302a1df09726ca7387b7b4ce089cfedc5fafef88 gpg: Signature made Tue Apr 12 16:14:13 2016 PDT using RSA key ID 9B3D0C19 gpg: Good signature from "Nishant Totla <firstname.lastname@example.org>" gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 672F 675C 8084 5DE2 C29A CFD3 7EA5 781C 9B3D 0C19 Author: Nishant Totla <email@example.com> Date: Tue Apr 12 16:14:13 2016 -0700 commit message Signed-off-by: Nishant Totla <firstname.lastname@example.org>
See the warning? It’s because GPG doesn’t know if this is a trusted key. That can be fixed by interactively editing they key
$ gpg --edit-key 9B3D0C19 gpg (GnuPG) 1.4.20; Copyright (C) 2015 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Secret key is available. pub 4096R/9B3D0C19 created: 2016-04-08 expires: 2032-04-04 usage: SC trust: unknown validity: unknown [ unknown] (1). Nishant Totla <email@example.com> gpg>
This opens a console to edit the key. In the console, type
trust and set the key to highest trust level.
gpg> trust pub 4096R/9B3D0C19 created: 2016-04-08 expires: 2032-04-04 usage: SC trust: unknown validity: unknown [ unknown] (1). Nishant Totla <firstname.lastname@example.org> Please decide how far you trust this user to correctly verify other users' keys (by looking at passports, checking fingerprints from different sources, etc.) 1 = I don't know or won't say 2 = I do NOT trust 3 = I trust marginally 4 = I trust fully 5 = I trust ultimately m = back to the main menu Your decision? 5 Do you really want to set this key to ultimate trust? (y/N) y pub 4096R/9B3D0C19 created: 2016-04-08 expires: 2032-04-04 usage: SC trust: ultimate validity: unknown [ unknown] (1). Nishant Totla <email@example.com> Please note that the shown key validity is not necessarily correct unless you restart the program. gpg> quit
To check that it worked
$ gpg --list-keys --list-options show-uid-validity /Users/NishantTotla/.gnupg/pubring.gpg -------------------------------------- pub 4096R/9B3D0C19 2016-04-08 [expires: 2032-04-04] uid [ultimate] Nishant Totla <firstname.lastname@example.org>
[ultimate] now shows up in the details. Try looking at commit logs again, and the problem should be fixed!
$ git log --show-signature -1 commit f2de8c24b72c2978126899dbe49cb8c9973ae00b gpg: Signature made Tue Apr 12 17:14:00 2016 PDT using RSA key ID 9B3D0C19 gpg: Good signature from "Nishant Totla <email@example.com>" Author: Nishant Totla <firstname.lastname@example.org> Date: Tue Apr 12 17:14:00 2016 -0700 commit message, this time with no warning Signed-off-by: Nishant Totla <email@example.com>
Note that it’s also possible to sign tags and merge commits.
Github recently announced that they would start showing a “Verified” tag on commits that were signed with a known GPG key. This requires uploading your public key to Github, so that it can verify signatures. You can do this in account settings
Github will now show a cool green tag against your signed commits!
If you faced any issues with these instructions, I’d love to hear feedback!- nRT