After my post about signed tags yesterday Kevin Ballard left a comment about a neat trick that lets you put the gpg public key used to sign tags into the repository itself. This explains how to do just that.
What this technique does is to add the gpg public key as a blob to the repository, but not as part of any branch. Normally, this would be cleaned up by git’s garbage collection, but by tagging this blob it gets a reference which means it isn’t orphaned so it persists.
So the repository will look like this:
It has one branch
master and two tags
v1.0 that tags version 1 and
pubkey that tags the public key.
The project was created and checked in as normal. But how do you add a file by itself without adding it to the project? We do this by adding it as a raw blob to the repository.Create the tagged public key
First. Lets get the gpg public key that we need. The email I am using for this repository as firstname.lastname@example.org (and I’ve set this up in the config file) so to get the public key as a plain text file I run:
gpg --armor --export <email@example.com> > pubkey.txt
git hash-object -w pubkey.txt
This will compute the hash of the object and the
-w flag gets the object written into the object database. It returns the hash value. you want to copy this. In my case it was
So now I can tag this blob, even though it isn’t in the index or part of the tree of commits:
git tag -s pubkey ab147894b92328ffef9db011789e4d0e55652688
This creates a signed tag called
pubkey that points to the blob that contains the public key. I didn’t need to use a signed tag, but it doesn’t hurt.
Now, I don’t need the
pubkey.txt file so I can delete it. Running
git status now should show that there is nothing more to do.
You can now tag other commits, as I have done with v1.0, and sign them. Remember when pushing your changes to remote repositories you need to push tags explicitly. You can use
git push origin --tags to push all tags or
git push origin pubkey to push just the pubkey tag (assuming your remote repository is named origin).
Now that the public key is in the repository, anybody who clones the repository can add the public key to their gpg keychain by:
git cat-file blob pubkey | gpg --import
This gets the contents of the blob pointed to by
pubkey which is the text version of the public key formatted for export and imports it to your own gpg keychain.
Now they can verify a signed tag, for example v1.0 by:
git tag -v v1.0
and the output will be something like this:
object d56fe222cd3d5fe5ac1709368c5c09cd496932df type commit tag v1.0 tagger Abizer Nasir <firstname.lastname@example.org> 1295369217 +0000 Tagging version 1.0 gpg: Signature made Tue 18 Jan 16:46:57 2011 GMT using RSA key ID 65875E7F gpg: Good signature from "Abizer Nasir <email@example.com>" 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: 9CC3 9E69 683B DD90 36DD 4622 FFD4 A90C 2D9E EF7B Subkey fingerprint: 83B8 FAA4 62BD 4821 49B3 5FE3 4F65 DD8F 6587 5E7F
The important thing here is to see the line that says that this is a good signature. The warning just says that you only have my word that this signature actually belongs to me. Those warnings tie in to the GPG web of trust which is beyond the scope of this site.
Have a look at the example repository and try it for yourself. As an exercise for the reader, why not sign my public key in your keychain so you don’t get these warning messages.FAQ
Why can’t I see the pubkey tag in my Git GUI?
Some of the visualisation tools, such as gitk don’t show tags that point to objects, only tags that point to commits. Which is why it is useful to use the command
git tag to show the tags in a repo.
How do I see what’s in a tag?
you can use
git cat-file -p <tagname> or
git show <tagname> which also shows a diff.
How do I get the SHA1 of the tag?
If you use the
git show-ref --tags command it brings up the SHA1 and the tag name. This is where you can get the SHA1 of the tag that points to the public key and post it somewhere so people can verify that the tag (and hence the public key) has not been changed.