Wednesday, June 4, 2014

Git commit/tag signing

It's interesting to look at the evolution of the git commit signing process.

A decade ago, in reaction to various legal events, Linus Torvalds proposed the adoption of a signing process for changes: Explicitly documenting patch submission:

So what I'm suggesting is that we start "signing off" on patches, to show the path it has come through, and to document that chain of trust. It also allows middle parties to edit the patch without somehow "losing" their names - quite often the patch that reaches the final kernel is not exactly the same as the original one, as it has gone through a few layers of people.

There was more discussion of this over the years, for example this email thread, in which Linus commented:

The thing is, what is it you want to protect? The tree, the authorship, the committer info, the commit log, what?

And it really does matter. Because the signature must be over some part of the commit, and since the SHA1 of the commit by definition contains everything, then the _safest_ thing is always to sign the SHA1 itself: thus a tag.

Anything else is always bound to only sign a _part_ of the commit. What part do you feel like protecting? Or put another way, what part do you feel like _not_ protecting?

So the way git does signatures protects everything. When you do a tag with "git tag -s" on a commit, you can absolutely _know_ that nobody will ever modify that commit in any way without the tag signature becoming invalid.

The process has stabilized, and is now documented in section 12 of How to Get Your Change Into the Linux Kernel, or, Care And Operation Of Your Linus Torvalds, where we read:

The sign-off is a simple line at the end of the explanation for the patch, which certifies that you wrote it or otherwise have the right to pass it on as an open-source patch. The rules are pretty simple: if you can certify the below:
        Developer's Certificate of Origin 1.1

        By making a contribution to this project, I certify that:

        (a) The contribution was created in whole or in part by me and I
            have the right to submit it under the open source license
            indicated in the file; or

        (b) The contribution is based upon previous work that, to the best
            of my knowledge, is covered under an appropriate open source
            license and I have the right under that license to submit that
            work with modifications, whether created in whole or in part
            by me, under the same open source license (unless I am
            permitted to submit under a different license), as indicated
            in the file; or

        (c) The contribution was provided directly to me by some other
            person who certified (a), (b) or (c) and I have not modified
            it.

 (d) I understand and agree that this project and the contribution
     are public and that a record of the contribution (including all
     personal information I submit with it, including my sign-off) is
     maintained indefinitely and may be redistributed consistent with
     this project or the open source license(s) involved.

then you just add a line saying

 Signed-off-by: Random J Developer 
using your real name (sorry, no pseudonyms or anonymous contributions.)

If you're studying processes like these, I really recommend you spend some time with Mike Gerwitz's epic mini-novella: A Git Horror Story: Repository Integrity With Signed Commits, at least to the level that you can follow its summary:

Be careful of who you trust. Is your repository safe from harm/exploitation on your PC? What about the PCs of those whom you trust?

Your host is not necessarily secure. Be wary of using remotely hosted repositories as your primary hub.

Using GPG to sign your commits can help to assert your identity, helping to protect your reputation from impostors.

For large merges, you must develop a security practice that works best for your particular project. Specifically, you may choose to sign each individual commit introduced by the merge, sign only the merge commit, or squash all commits and sign the resulting commit.

If you have an existing repository, there is little need to go rewriting history to mass-sign commits.

Once you have determined the security policy best for your project, you may automate signature verification to ensure that no unauthorized commits sneak into your repository.

No comments:

Post a Comment