设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

Git使用中的教训:签名提交确保代码完整可信

2014-9-23 10:53| 发布者: joejoe0332| 查看: 7799| 评论: 0|原作者: 几点人, 无若, petert, Sophietyl, f4f, sg90, 请叫我益达张|来自: oschina

摘要: GIT是一款分布式版本控制系统。简而言之,这意味着任何人可以私自拥有一份你的仓库的副本(copy)进行线下工作。他们可能提交版本到自己的仓库,也可以相互之间进行push和pull。中心仓库对分布式版本控制系统来说不是 ...


信任保障

如果我们有一种方法去确认提交是通过某个被叫做“Mike Gerwitz”的人提交的,而实际上是我用我自己的e-mail地址提交的,就像实际上是我使用我的私钥打的标签, 我们就可以断言一个标签的签署吗?是的,我们试图去证明我们是谁?如果你仅仅提供你的标识给一个项目的作者/维护者,然后你要用任何合理的方式去标识你自己。举个例子:如果你的工作中有同样的内部网络,那么你可以从内部IP中确认是安全的。如果发送是通过e-mail,你可以用你的GPG钥匙来签署补丁。不幸地是,这仅仅是对作者/维护者这一层信任级的扩展,没有其他用户!如果我去克隆你的库并且查看历史记录,我怎么做才能知道提交是来自于“Foo Bar”而且还是来自Foo Bar的可信的提交,尤其是如果库频繁地接收来自用户的补丁和合并这些请求,如何确保是可信的?

以前,仅仅只是在打标签时使用GPG。幸运地是,Git v1.7.9 据说支持对单个的提交将可以使用GPG签署——这个特性我已经期待很久了。考虑到可能发生文章开头那样的故事,如果你对每一个提交进行签署,类似这样:

1
$ git commit -S -m 'Fixed security vulnerability CVE-123'#             ^ GPG-sign commit


  注意上面例子中的「-S」,它告诉Git用你的GPG公钥来提交变更的代码(请注意「-s」和「-S」的区别)。如果你毫无例外的每一次都用你的GPG公钥来提交代码,那么你(或者其他人)就可以相当肯定变更是否真的是你自己提交的。在上面的故事中,你就可以保护自己,指出后门代码不是你提交的,因为你的代码都有GPG公钥签名。(当然,别人也可能说你是想好这个借口而故意不签名的。后面将会稍稍讨论一下这个问题。) 
为了设置你的GPG公钥签名,你首先要用gpg --list-secret-keys命令得到你的GPG公钥: 

1
2
$ gpg --list-secret-keys | grep ^sec
sec   4096R/8EE30EAB 2011-06-16 [expires: 2014-04-18]#           ^^^^^^^^


  你感兴趣的就是上面的输出中斜杠后面的16进制值。(你的输出可能跟上面相差很大,即使没有上面的4096R你也不用担心)。如果你有多个公钥,选择其中一个作为你的签名。这个16进制值需要设置到Git的环境变量user.signingkey中: 

1
2
# remove --global to use this key only on the current repository
$ git config --global user.signingkey 8EE30EAB#                                        ^ replace with your key id

接下来,就让我们来试一下带签名的提交。首先要建立一个测试用的代码仓库,后面的文章会在这个代码仓库上做实验。 

1
2
3
4
5
mkdir tmp && cd tmp
$ git init .$ echo foo > foo
$ git add foo
$ git commit -S -m 'Test commit of foo'You need a passphrase to unlock the secret key foruser: "Mike Gerwitz (Free Software Developer) <mike@mikegerwitz.com>"4096-bit RSA key, ID 8EE30EAB, created 2011-06-16[master (root-commit) cf43808] Test commit of foo 1 file changed, 1 insertion(+)
 create mode 100644 foo

  此时的提交与未签名的提交唯一不同的地方是增加了-S选项,这个选项表明我们要求的是具有GPG签名的提交。如果一切设置正确,那么就应该会提示你输入密钥对应的密码(如果你运行了gpg代理,那么就不会有任何提示),然后提交就像你所期望的那样继续运行,最终的结果就像上面输出所示(你的GPG详细信息和SHA-1哈希值会有所不同)。


  默认情况下(至少在Git 1.7.9版本),git log不会列出或者验证签名。要显示提交所对应的签名,我们可以使用--show-signature 选项,如下:

1
2
3
4
5
6
7
8
$ git log --show-signature
commit cf43808e85399467885c444d2a37e609b7d9e99d
gpg: Signature made Fri 20 Apr 2012 11:59:01 PM EDT using RSA key ID 8EE30EAB
gpg: Good signature from "Mike Gerwitz (Free Software Developer) <mike@mikegerwitz.com>"
Author: Mike Gerwitz <mike@mikegerwitz.com>
Date:   Fri Apr 20 23:59:01 2012 -0400
 
    Test commit of foo


  此时最大的不同是:提交者和本次提交对应的签名可能指的是不同的两个人。换句话说:提交的签名在理念上与-s选项相似,它给提交增加了签名---这么做确保你对提交进行了签名,但并不能说明你提交的就是你所修改的。为了说明这个问题,想想我们接收并希望应用来自“John Doe"的补丁。代码仓库的策略是每次提交都必须由可信赖的个人进行签名;而所有其他提交都会被项目管理者拒绝。为了说明不费周折就能采用真正的补丁,我们只要按照以下步骤去做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
echo patch from John Doe >> foo
$ git commit -S --author="John Doe <john@doe.name>" -am 'Added feature X'
You need a passphrase to unlock the secret key for
user: "Mike Gerwitz (Free Software Developer) <mike@mikegerwitz.com>"
4096-bit RSA key, ID 8EE30EAB, created 2011-06-16
 
[master 16ddd46] Added feature X
 Author: John Doe <john@doe.name>
 file changed, 1 insertion(+)
$ git log --show-signature
commit 16ddd46b0c191b0e130d0d7d34c7fc7af03f2d3e
gpg: Signature made Sat 21 Apr 2012 12:14:38 AM EDT using RSA key ID 8EE30EAB
gpg: Good signature from "Mike Gerwitz (Free Software Developer) <mike@mikegerwitz.com>"
Author: John Doe <john@doe.name>
Date:   Sat Apr 21 00:14:38 2012 -0400
 
    Added feature X# [...]

  这就会产生问题---对于那些用自己的GPG密钥签名提交的人来说,我们该怎么做呢?要从两个角度来分析这个问题。首先,从项目管理者角度考虑这个问题--我们是否需要仔细确认第三方贡献者的身份,还是只接收其提供的代码? 这要看具体情况。另外,从法律的角度来看,我们可能需要确认身份,但并不是每个用户都有GPG密钥。想想这种情况:某个人只是为了签名几次提交而不需要对其身份进行验证而创建了密钥,后来就丢弃了这个密钥(或者说忘记了这个密钥),那么他就不会为验证身份而提供更多信息。(事实上,PGP的整体理念是创建一个可信任的站点,一边能够验证使用自己密钥签名的人能够真实地说出自己是谁,因此使用的场景重要,而目的不重要。)因此,对贡献补丁的每个人采用严格的签名策略可能是失败的。Linux 和Git在提交中采用“签名”满足了法律方面的要求,这就意味着创建者同意了采用“ 
原始开发者证书”;这实际上也说明创建者对提交里包含的代码有法律上的拥有权。什么时候开始接受来自可信任站点之外的第三方的补丁是接下来将要做的事。

  对补丁采用这种方针,需要作者们做下面的事,而不需要他们用GPG来签名:

1
2
3
4
5
6
7
$ git commit -asm 'Signed off'#              ^ -s flag adds Signed-off-by line$ git log
commit ca05f0c2e79c5cd712050df6a343a5b707e764a9
Author: Mike Gerwitz <mike@mikegerwitz.com>Date:   Sat Apr 21 15:46:05 2012 -0400
 
    Signed off
 
    Signed-off-by: Mike Gerwitz <mike@mikegerwitz.com># [...]


  当你收到这样的补丁,你可以用「-S」(大写S)来进行GPG签名并提交;这样同时会保留作者的 Signed-off-by签名行。对于一个pull请求,你可以通过修改来签名提交(git commit -S --amend)。注意,这样做会改变提交的SHA-1哈希值。


  万一你想保留提出pull请求的人的签名行呢?你不能修改提交,因为这样会使对方的签名无效,所以双重签名不可行(即使Git以后支持双重签名)。不过,你可以考虑对合并后的代码进行签名,我们将在下一节来讨论这个问题。



酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部