One useful feature of Bazaar is the ability to
cryptographically sign revisions. I was discussing this with
Ryan on IRC, and thought I'd write up
some of the details as they might be useful to others.
Anyone who remembers the past security of GNOME
and Debian servers should be able to
understand the benefits of being able to verify the integrity of a
source code repository after such an incident. Rather than requiring all
revisions made since the last known safe backup to be examined, much of
the verification could be done mechanically.
Turning on Revision Signing
The first thing you'll need to do is get a
PGP key and
configure GnuPG to use it. The GnuPG
is a good reference on doing this. As the aim is to provide some
assurance that the revisions you publish were really made by you, it'd
be good to get the key signed by someone.
Once that is done, it is necessary to configure Bazaar to sign new
revisions. The easiest way to do this is to edit
to look something like this:
email = My Name <firstname.lastname@example.org>
create_signatures = always
Now when you run "
bzr commit", a signature for the new revision will
be stored in the repository. With this configuration change, you will be
prompted for your pass phrase when making commits. If you'd prefer not
to enter it repeatedly, there are a few options available:
gpg-agent, and use it to remember your pass phrase in the
same way you use ssh-agent.
- install the
gnome-gpg wrapper, which lets you remember your pass
phrase in your Gnome keyring. To use
gnome-gpg, you will need to
add an additional configuration value:
gpg_signing_command = gnome-gpg".
Signatures are transferred along with revisions when you push or pull a
branch, perform merges, etc.
How Does It Work?
So what does the signature look like, and what does it cover? There is
no command for printing out the signatures, but we can access them using
bzrlib. As an example, lets look at the signature on the head revision
of one of my branches:
>>> from bzrlib.branch import Branch
>>> b = Branch.open('http://bazaar.launchpad.net/~jamesh/storm/reconnect')
>>> print b.repository.get_signature_text(b.last_revision())
-----BEGIN PGP SIGNED MESSAGE-----
bazaar-ng testament short form 1
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
-----END PGP SIGNATURE-----
If we save this signature to a file, we can verify it with a command
gpg --verify signature.txt" to prove that it was made using my
PGP key. Looking at the signed text, we see three lines:
- An identifier for the checksum algorithm. This is included to future
proof old signatures should the need arise to alter the checksum
algorithm at a later date.
- The revision ID that the signature applies to. Note that this is the
full globally unique identifier rather than the shorter numeric
identifiers that are only unique in the context of an individual
- The checksum, in SHA1 form.
For the current signing algorithm, the checksum is made over the long
form testament for the revision, which can easily be verified:
$ bzr branch http://bazaar.launchpad.net/~jamesh/storm/reconnect
$ cd reconnect
$ bzr testament --long > testament.txt
$ sha1sum testament.txt
Looking at the long form testament, we can see what the signature
- The revision ID
- The name of the committer
- The date of the commit
- The parent revision IDs
- The commit message
- A list of the files that comprise the source tree for the revision,
along with SHA1 sums of their contents
- Any revision properties
So if the revision testament matches the revision signature and the
revision signature validates, you can be sure that you are looking at
the same code as the person who made the signature.
It is worth noting that while the signature makes an assertion about the
state of the tree at that revision -- the only thing it tells you about
the ancestry is the revision IDs of the parents. If you need assurances
about those revisions, you will need to check their signatures
separately. One of the reasons for this is that you might not know the
full history of a branch if it has ghost
revisions (as might happen when
importing code from certain foreign version control systems).
Signing Past Revisions
If you've already been using Bazaar but had not enabled revision
signing, it is likely that you've got a bunch of unsigned revisions
lying around. If that is the case, you can sign the revisions in bulk
using the "bzr sign-my-commits" command. It will go through all
revisions in the ancestry, and generate signatures for all the commits
that match your committer ID.
Verifying Signatures in Bulk
To verify all signatures found in a repository, John Arbash Meinel's
signing plugin can be used, which provides a "bzr verify-sigs"
command. It can be installed with the following commands:
$ mkdir -p ~/.bazaar/plugins
$ bzr branch http://bzr.arbash-meinel.com/plugins/signing/ ~/.bazaar/plugins/signing
When the command is run it will verify the integrity of all the
signatures, and give a summary of how many revisions each person has
Fantastic post! This is exactly why I read the planets. Thanks!