365Git

Month

January 2011

2 posts

Adding a GPG Public Key to a repository

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.

As a practical example I’ll use this Hello World repository on GitHub.

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 abizern@abizern.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 <abizern@abizern.org> > pubkey.txt

The actual name of the file doesn’t matter because a blob only stores the contents of a file. Now we can turn this file into a blob with:

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

ab147894b92328ffef9db011789e4d0e55652688

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).

Verify signed tags.

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 <abizern@abizern.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 <abizern@abizern.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: 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.

Jan 18, 201133 notes
#git #gpg #publickey #tags #signed #blob #github
Signing a Git Tag

I’ve already written about the Git Tag Object and made a passing reference to signed tags.

Git doesn’t make any checks about whether the name and email you enter into a git config file really is you, so it’s trivial make a check-in that looks like it’s been made by someone else. But, if you have some form of GPG installed, you can cryptographically sign a tag object (not a lightweight tag) than can be verified as being created by you.

Since a tag object references a commit, which in turn references another commit, and so on, a tag verifies a whole tree of commits. Changing any of the commits, or the tag, would mean new objects would be created that would break this tree. So by signing a tag, which points to a commit, a whole section of the code history is being validated by someone. And if you trust that person, and you trust his public key, you can verify that the tag was created by that person.

To create a signed tag, just pass the -s flag instead of the -a flag:

git tag -s -m"tagging version 1.0" v1.0

This will create a signed tag object called v1.0 with the passed commit message and it will use the signing identity of the committer (if there is a key for that). The documentation for git-config states that you can set a key for user.signingkey that will be used by default to sign commits, but I’ve found that I don’t need to do this as the correct key is used based on the user.email that I am using. A prompt will come up asking you for your key’s passphrase.

If you want to use a particular signing identity when tagging then use then use:

git tag -u <key-id> -m"tagging version 1.0" v1.0

Here, the -u <key-id> specifies the key to use.

Also, as with commit messages, if you leave out the message an editor will be brought up for you to enter the tag message.

The signed tag object is only slightly different from the unsigned tag object in that it has a PGP signature block. To verify the signature use the -v flag of the tag command

git tag -v v1.0

and if you have the correct public key for the user in your GPG Keychain it will let you know if the signature is valid or not.

In my earlier post I also mentioned that a tag object does not have to point at a commit; it can point to any other git object. In this way, you can also tag individual files or trees or even other tags if you are paranoid enough to want to. But this does nothing more than putting a name to a tag, or a commit. It establishes nothing more than responsibility - not a guarantee of quality nor of the origin of the work.

Jan 17, 201121 notes
#git #tag #gpg #signed #cryptographically
Next page →
2010 2011
  • January 2
  • February 2
  • March 1
  • April 1
  • May
  • June
  • July
  • August
  • September
  • October
  • November 2
  • December
2010 2011
  • January
  • February
  • March 8
  • April 17
  • May
  • June
  • July
  • August
  • September
  • October
  • November
  • December