GPG signing for git commit?

17 messages, 9 authors, 2016-06-15 · open the first message on its own page

GPG signing for git commit?

From: Chow Loong Jin <hidden>
Date: 2016-06-15 22:46:33

Hi,

It crossed my mind that currently git commits cannot actually be
verified to be authentic, due to the fact that I can just set my
identity to be someone else, and then commit under their name. During
discussion on #git, Ilari, context and I figured that it would be a good
idea to get GPG signing on git commits, considering that git-tag already
has GPG signing support.

Attached is the transcript of the log, with some irrelevant bits chopped
out. Log is dated Sat, April 4, and timezone GMT +0800.

-- 
Chow Loong Jin

Re: GPG signing for git commit?

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: 2016-06-15 22:46:33


On Sat, 4 Apr 2009, Chow Loong Jin wrote:
It crossed my mind that currently git commits cannot actually be
verified to be authentic, due to the fact that I can just set my
identity to be someone else, and then commit under their name.
You can't do that.

Well, you can, but it's always going to be inferior to just adding a tag. 

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. 

And perhaps equally interestingly, that signature is now also easily 
separable from the history - which is interesting if you want to 
distribute your cryptographic parts separately (for example, you only use 
it _internally_ within a company or group, to mark some group-specific 
issues).

Also, related to that "separable" - the person signing on something is not 
necessarily the person marked as author, or even committing it anyway. One 
of the guiding goals for git was always that it should work well with 
"outside" flows, ie others passing patches around or using other SCM's to 
manage their own flow. 

Finally, on that same "separable" notion - imagine a big rewrite operation 
for whatever reason - like a big import into git, or a project re-writing 
their history because they ended up importing more history from old 
sources (or because they wanted to split a big project into subprojects). 
All of those invalidate any cryptographic signatures.

And all of those are events that you may still want to _update_ the 
signatures, but do you want to trust the one doing the conversion with the 
private keys? Obviously not. You could "wrap" the signing in a new 
"conversion signature", and have a signature to try to imply that the 
person doing the conversion "signs" the conversion. But the fact is, that 
doesn't mean the same thing.

With separate signatures (ie the "git tag -s" model), you can ask the 
people who signed the original repository to consider re-signing the 
rewritten one. See? Safe, flexible, and much superior.

The exact same thing goes for keys that get invalidated because they ended 
up being shown to be too weak or just flawed some other way, btw. That is 
a reason to re-sign, _without_ the repository necessarily changing.

You can do _none_ of these things sanely if you put the signatures into 
the commits themselves. 

So don't do it.

Btw, there's a final reason, and probably the really real one. Signing 
each commit is totally stupid. It just means that you automate it, and you 
make the signature worth less. It also doesn't add any real value, since 
the way the git DAG-chain of SHA1's work, you only ever need _one_ 
signature to make all the commits reachable from that one be effectively 
covered by that one. So signing each commit is simply missing the point. 

IOW, you don't _ever_ have a reason to sign anythign but the "tip". The 
only exception is the "go back and re-sign", but that's the one that 
requires external signatures anyway.

So be happy with 'git tag -s'. It really is the right way.

		Linus

Re: GPG signing for git commit?

From: Sam Vilain <hidden>
Date: 2016-06-15 22:46:33

Linus Torvalds wrote:
On Sat, 4 Apr 2009, Chow Loong Jin wrote:
  
quoted
It crossed my mind that currently git commits cannot actually be
verified to be authentic, due to the fact that I can just set my
identity to be someone else, and then commit under their name.
    
You can't do that.

Well, you can, but it's always going to be inferior to just adding a tag. 

The thing is, what is it you want to protect? The tree, the authorship, 
the committer info, the commit log, what?
  
[...]
Btw, there's a final reason, and probably the really real one. Signing 
each commit is totally stupid. It just means that you automate it, and you 
make the signature worth less. It also doesn't add any real value, since 
the way the git DAG-chain of SHA1's work, you only ever need _one_ 
signature to make all the commits reachable from that one be effectively 
covered by that one. So signing each commit is simply missing the point. 

IOW, you don't _ever_ have a reason to sign anythign but the "tip". The 
only exception is the "go back and re-sign", but that's the one that 
requires external signatures anyway.

So be happy with 'git tag -s'. It really is the right way.
  
Linus I agree with these points - I'd just like to point you to the new
mirror-sync design document. Under Documentation/git-mirror-sync.txt on
http://github.com/samv/git/tree/mirror-sync - and an implementation plan
outlined in Documentation/git-mirror-sync-impl.txt

This system allows for *pushes* to be signed and in general laying the
foundation for knowing that commits are authentic without the intrusion
into the refs/tags/* space that making lots of signed tags would imply.
The idea is to put 'packed-refs' contents (or a moral equivalent) in tag
bodies. It is really a new type of object, but it's sufficiently similar
to a tag that I thought I'd just go and go with that design for now.
Anyway if you're curious take a look, otherwise wait for the formal
submission once I've got something better together...

Sam

Re: GPG signing for git commit?

From: Jakub Narebski <hidden>
Date: 2016-06-15 22:46:34

Linus Torvalds [off-list ref] writes:
On Sat, 4 Apr 2009, Chow Loong Jin wrote:
quoted
It crossed my mind that currently git commits cannot actually be
verified to be authentic, due to the fact that I can just set my
identity to be someone else, and then commit under their name.
[...]
Btw, there's a final reason, and probably the really real one. Signing 
each commit is totally stupid. It just means that you automate it, and you 
make the signature worth less. It also doesn't add any real value, since 
the way the git DAG-chain of SHA1's work, you only ever need _one_ 
signature to make all the commits reachable from that one be effectively 
covered by that one. So signing each commit is simply missing the point. 

IOW, you don't _ever_ have a reason to sign anythign but the "tip". The 
only exception is the "go back and re-sign", but that's the one that 
requires external signatures anyway.

So be happy with 'git tag -s'. It really is the right way.
And if you really, really need for some reason (for example
requirement checkpoint, or being paranoid enough) ned to have each and
every commit signed, you can use Monotone instead of Git.  That is
what we recommended IPsec (or something) on #git.

-- 
Jakub Narebski
Poland
ShadeHawk on #git

Re: GPG signing for git commit?

From: Linus Torvalds <torvalds@linux-foundation.org>
Date: 2016-06-15 22:46:34


On Tue, 7 Apr 2009, Jakub Narebski wrote:
And if you really, really need for some reason (for example
requirement checkpoint, or being paranoid enough) ned to have each and
every commit signed, you can use Monotone instead of Git.  That is
what we recommended IPsec (or something) on #git.
Yeah, well..

That's more of a "If you really want to be incredibly slow, depend on an 
unbelievably baroque model, _and_ you are too stupid to understand the 
fact that you only need to sign the tip", then use Monotone.

But yes, the "sign each commit" is one of the big design mistakes in 
Monotone. Go ask them about how much pain it has caused them.

			Linus

Re: GPG signing for git commit?

From: Robin H. Johnson <hidden>
Date: 2016-06-15 22:46:36

On Mon, Apr 06, 2009 at 06:05:38PM +1200, Sam Vilain wrote:
This system allows for *pushes* to be signed and in general laying the
foundation for knowing that commits are authentic without the intrusion
into the refs/tags/* space that making lots of signed tags would imply.
I'm on the lookout for something similar, so that we can be sure who
introduced some change into the central repo.

One of the spots that we're looking for in this, is a model something
like what follows. Firstly, a "proxy maintainer" (PM) is a developer
with commit rights to the central repo, that's willing to proxy commits
by an outside source for some specific package. Think of them as the
kernel subsystem maintainer, but many more of them. The PM is still
expected to verify the work before passing it on the central repo.

So we have a commit with author+committer being the outside source, and
now we want to record (in an easily reviewable fashion) that a specific
changeset was introduced to the central tree by the PM.

Not sure of the best route to trace this data. Signing the SHA1 makes
the most sense, but need to be able to do that without polluting the tag
namespace.

If the changeset does not have an associated signature, we'd like to
reject it at the central repo.

-- 
Robin Hugh Johnson
Gentoo Linux Developer & Infra Guy
E-Mail     : robbat2@gentoo.org
GnuPG FP   : 11AC BA4F 4778 E3F6 E4ED  F38E B27B 944E 3488 4E85

Re: GPG signing for git commit?

From: Shawn O. Pearce <hidden>
Date: 2016-06-15 22:46:36

"Robin H. Johnson" [off-list ref] wrote:
One of the spots that we're looking for in this, is a model something
like what follows. Firstly, a "proxy maintainer" (PM) is a developer
with commit rights to the central repo, that's willing to proxy commits
by an outside source for some specific package. Think of them as the
kernel subsystem maintainer, but many more of them. The PM is still
expected to verify the work before passing it on the central repo.

So we have a commit with author+committer being the outside source, and
now we want to record (in an easily reviewable fashion) that a specific
changeset was introduced to the central tree by the PM.

Not sure of the best route to trace this data. Signing the SHA1 makes
the most sense, but need to be able to do that without polluting the tag
namespace.
Have the PM push over SSH, and don't ever expire reflogs on the
central repository?  The reflog will have the old and new commits
and the user name of the PM.

Downsides are:

- data is in the reflog on the central repository, to access it
  you need to expose that file via some non-git means (e.g. http
  or direct shell).

- one reflog record may cover multiple commits, so looking up a
  single commit is very difficult.  no current tools exist to merge
  the reflog back against the commit history to attach the record
  to a range of commits.

- the reflog is a text file, it will get somewhat large with time.

- the reflog is destroyed when the branch is deleted.  you may need a
  hook to forbid deletion of critical branches, so the reflog stays.

-- 
Shawn.

Re: GPG signing for git commit?

From: Robin H. Johnson <hidden>
Date: 2016-06-15 22:46:36

On Wed, Apr 15, 2009 at 12:20:54PM -0700, Shawn O. Pearce wrote:
quoted
Not sure of the best route to trace this data. Signing the SHA1 makes
the most sense, but need to be able to do that without polluting the tag
namespace.
Have the PM push over SSH, and don't ever expire reflogs on the
central repository?  The reflog will have the old and new commits
and the user name of the PM.
All pushing to the central repo will be git+ssh:// anyway.

I don't follow where the PM's identity is being stored, and how that's
distributed back out with the later pulls.

The other downside to relying on SSH presentation of identity directly,
is the inability to use the SSH key to uniquely identify the user during
the SSH auth (see designs like gitosis, where you always push to
git+ssh://git@host/repo).

-- 
Robin Hugh Johnson
Gentoo Linux Developer & Infra Guy
E-Mail     : robbat2@gentoo.org
GnuPG FP   : 11AC BA4F 4778 E3F6 E4ED  F38E B27B 944E 3488 4E85

Re: GPG signing for git commit?

From: Shawn O. Pearce <hidden>
Date: 2016-06-15 22:46:36

"Robin H. Johnson" [off-list ref] wrote:
On Wed, Apr 15, 2009 at 12:20:54PM -0700, Shawn O. Pearce wrote:
quoted
quoted
Not sure of the best route to trace this data. Signing the SHA1 makes
the most sense, but need to be able to do that without polluting the tag
namespace.
Have the PM push over SSH, and don't ever expire reflogs on the
central repository?  The reflog will have the old and new commits
and the user name of the PM.
All pushing to the central repo will be git+ssh:// anyway.

I don't follow where the PM's identity is being stored, and how that's
distributed back out with the later pulls.
Its stored in the reflog for the branch; see "git log -g branch".
Technically the environment variable GIT_COMMITTER_NAME and
GIT_COMMITTER_EMAIL is used to populate the identity into the reflog,
but if these aren't set then its guessed from the gecos information
of the effective user.
 
The other downside to relying on SSH presentation of identity directly,
is the inability to use the SSH key to uniquely identify the user during
the SSH auth (see designs like gitosis, where you always push to
git+ssh://git@host/repo).
Uhm, yea.  That's a fault of gitosis then.  It knows the key that
was used, and has that mapped back to some token that identifies that
account in the configuration file.  Why it doesn't push that into the
GIT_COMMITTER_* environment before launching git-shell, I don't know.

<plug type="shameless">

My day-job project, Gerrit Code Review[1], actually does the right
thing by recording the identity of the user in the reflog...

</plug>


[1] http://code.google.com/p/gerrit/

-- 
Shawn.

Re: GPG signing for git commit?

From: Sitaram Chamarty <hidden>
Date: 2016-06-15 22:46:36

On 2009-04-16, Shawn O. Pearce [off-list ref] wrote:
quoted
The other downside to relying on SSH presentation of identity directly,
is the inability to use the SSH key to uniquely identify the user during
the SSH auth (see designs like gitosis, where you always push to
git+ssh://git@host/repo).
Uhm, yea.  That's a fault of gitosis then.  It knows the key that
was used, and has that mapped back to some token that identifies that
account in the configuration file.  Why it doesn't push that into the
GIT_COMMITTER_* environment before launching git-shell, I don't know.
If you set GIT_COMMITTER_*, won't it change the SHA of the
commit itself?  I always thought so...

One possibility is to set "LogLevel VERBOSE" in
/etc/ssh/sshd_config and save those logs -- they can help
you match up the timestamps in the reflogs and find out who
pushed what, subject to all the other caveats in Shawn's
earlier post.

But it's a kludge... sadly my python-fu is zero; I really
wish gitosis would put that info *somewhere*.

Re: GPG signing for git commit?

From: Jeff King <hidden>
Date: 2016-06-15 22:46:36

On Fri, Apr 17, 2009 at 03:42:07AM +0000, Sitaram Chamarty wrote:
quoted
Uhm, yea.  That's a fault of gitosis then.  It knows the key that
was used, and has that mapped back to some token that identifies that
account in the configuration file.  Why it doesn't push that into the
GIT_COMMITTER_* environment before launching git-shell, I don't know.
If you set GIT_COMMITTER_*, won't it change the SHA of the
commit itself?  I always thought so...
No. Pushing will never create a new commit, so there are no new SHA-1s
calculated. But the reflog entry will contain GIT_COMMITTER_*, and is a
simple text file.

-Peff

Re: GPG signing for git commit?

From: Sitaram Chamarty <hidden>
Date: 2016-06-15 22:46:37

On 2009-04-17, Jeff King [off-list ref] wrote:
quoted
If you set GIT_COMMITTER_*, won't it change the SHA of the
commit itself?  I always thought so...
No. Pushing will never create a new commit, so there are no new SHA-1s
calculated. But the reflog entry will contain GIT_COMMITTER_*, and is a
simple text file.
cool -- I didn't know this.  Thanks!

One last question: where do you set it, in the pre-commit
hook on the server?

Re: GPG signing for git commit?

From: Jeff King <hidden>
Date: 2016-06-15 22:46:38

On Fri, Apr 17, 2009 at 06:36:40PM +0000, Sitaram Chamarty wrote:
On 2009-04-17, Jeff King [off-list ref] wrote:
quoted
quoted
If you set GIT_COMMITTER_*, won't it change the SHA of the
commit itself?  I always thought so...
No. Pushing will never create a new commit, so there are no new SHA-1s
calculated. But the reflog entry will contain GIT_COMMITTER_*, and is a
simple text file.
cool -- I didn't know this.  Thanks!

One last question: where do you set it, in the pre-commit
hook on the server?
No, for two reasons:

  1. The pre-commit hook is run when making a local commit. For pushing,
     you would want the pre-receive hook.

  2. Hooks are executed as child processes of receive-pack, so they
     can't impact the environment it sees.

I think you would need to intercept the call to receive-pack (e.g., by
replacing it with a wrapper script), set the variables based on ssh keys
used (or whatever criteria you want), and then exec receive-pack.

-Peff

Re: GPG signing for git commit?

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:46:43

On Thu, Apr 16, 2009 at 4:55 AM, Robin H. Johnson [off-list ref] wrote:
One of the spots that we're looking for in this, is a model something
like what follows. Firstly, a "proxy maintainer" (PM) is a developer
with commit rights to the central repo, that's willing to proxy commits
by an outside source for some specific package. Think of them as the
kernel subsystem maintainer, but many more of them. The PM is still
expected to verify the work before passing it on the central repo.

So we have a commit with author+committer being the outside source, and
now we want to record (in an easily reviewable fashion) that a specific
changeset was introduced to the central tree by the PM.

Not sure of the best route to trace this data. Signing the SHA1 makes
the most sense, but need to be able to do that without polluting the tag
namespace.

If the changeset does not have an associated signature, we'd like to
reject it at the central repo.
How about signing the tree SHA-1 and putting the signature in commit
message? It's like gpg way of saying Signed-off-by. If the committer
wants to sign again before pushing out, he could amend the commit,
append his signature there; or make a no-change commit to contain his
signature (probably from git-commit-tree because iirc git-commit won't
let you make no-change commit)
-- 
Duy

Re: GPG signing for git commit?

From: Robin H. Johnson <hidden>
Date: 2016-06-15 22:46:44

On Thu, May 07, 2009 at 03:30:51PM +1000, Nguyen Thai Ngoc Duy wrote:
On Thu, Apr 16, 2009 at 4:55 AM, Robin H. Johnson [off-list ref] wrote:
quoted
One of the spots that we're looking for in this, is a model something
like what follows. Firstly, a "proxy maintainer" (PM) is a developer
with commit rights to the central repo, that's willing to proxy commits
by an outside source for some specific package. Think of them as the
kernel subsystem maintainer, but many more of them. The PM is still
expected to verify the work before passing it on the central repo.

So we have a commit with author+committer being the outside source, and
now we want to record (in an easily reviewable fashion) that a specific
changeset was introduced to the central tree by the PM.

Not sure of the best route to trace this data. Signing the SHA1 makes
the most sense, but need to be able to do that without polluting the tag
namespace.

If the changeset does not have an associated signature, we'd like to
reject it at the central repo.
How about signing the tree SHA-1 and putting the signature in commit
message? It's like gpg way of saying Signed-off-by. If the committer
wants to sign again before pushing out, he could amend the commit,
append his signature there; or make a no-change commit to contain his
signature (probably from git-commit-tree because iirc git-commit won't
let you make no-change commit)
Hmm, I like the sound of that, but I'm concerned it might be difficult
to enforce. If rewrite-history ever happens, it's also invalidated.

-- 
Robin Hugh Johnson
Gentoo Linux Developer & Infra Guy
E-Mail     : robbat2@gentoo.org
GnuPG FP   : 11AC BA4F 4778 E3F6 E4ED  F38E B27B 944E 3488 4E85

Re: GPG signing for git commit?

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:46:44

On Sat, May 9, 2009 at 5:03 AM, Robin H. Johnson [off-list ref] wrote:
quoted
How about signing the tree SHA-1 and putting the signature in commit
message? It's like gpg way of saying Signed-off-by. If the committer
wants to sign again before pushing out, he could amend the commit,
append his signature there; or make a no-change commit to contain his
signature (probably from git-commit-tree because iirc git-commit won't
let you make no-change commit)
Hmm, I like the sound of that, but I'm concerned it might be difficult
to enforce. If rewrite-history ever happens, it's also invalidated.
Well if you rewrite and touch the trees, then every signature should
be invalidated anyway. If you only touch commit message, it should
remain valid because I only sign trees.
-- 
Duy

Re: GPG signing for git commit?

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:46:44

On Mon, May 11, 2009 at 8:53 AM, Nguyen Thai Ngoc Duy [off-list ref] wrote:
On Sat, May 9, 2009 at 5:03 AM, Robin H. Johnson [off-list ref] wrote:
quoted
quoted
How about signing the tree SHA-1 and putting the signature in commit
message? It's like gpg way of saying Signed-off-by. If the committer
wants to sign again before pushing out, he could amend the commit,
append his signature there; or make a no-change commit to contain his
signature (probably from git-commit-tree because iirc git-commit won't
let you make no-change commit)
Hmm, I like the sound of that, but I'm concerned it might be difficult
to enforce. If rewrite-history ever happens, it's also invalidated.
Well if you rewrite and touch the trees, then every signature should
be invalidated anyway. If you only touch commit message, it should
remain valid because I only sign trees.
I went ahead and made two scripts git-gpg-sign and git-gpg-verify to
see if it works. Things that are signed in these scripts:
 - tree
 - parents
 - any other gpg signature
You probably don't want to sign the same commit too many times because
the signature will get huge.
-- 
Duy
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help