GPG 签署 git commit 提供什么保证?

信息安全 电子签名 gnupg 混帐
2021-09-06 07:36:51

很明显,GPG 签名和 GitHub ssh 密钥有不同的用途

但是 GPG 签名提交有什么用呢?只是您知道提交abcd1234是由 Alice 的密钥签名的吗?GPG 签署提交还有什么用处吗?

1个回答

使用 git,分支顶端的加密签名为该分支向后追溯的整个历史提供强大的完整性保证,包括存储库的所有元数据和所有内容,一直到初始提交这是可能的,因为 git 在每个下一次提交的元数据中记录了上一次提交的哈希,从而创建了一个牢不可破的加密记录链。如果您可以验证分支顶端的加密签名,您就可以有效地验证该分支的整个历史记录。

例如,让我们看一下 linux.git,在撰写本文时,最新的标签v5.5-rc4, 是由 Linus Torvalds 签名的。(这与您的问题略有不同,因为您询问了有关签署提交的问题,而我们正在查看已签署的标签——但在每个实际意义上,这都是完全相同的。)

$ git cat-file -p v5.5-rc4
object fd6988496e79a6a4bdb514a4655d2920209eb85d
type commit
tag v5.5-rc4
tagger Linus Torvalds <torvalds@linux-foundation.org> 1577662169 -0800

Linux 5.5-rc4
-----BEGIN PGP SIGNATURE-----

iQFSBAABCAA8FiEEq68RxlopcLEwq+PEeb4+QwBBGIYFAl4JNtkeHHRvcnZhbGRz
...
=rNsn
-----END PGP SIGNATURE-----

这个标签的全部内容都被签名了,所以这告诉我们,当 Linus 对标签进行签名时,他系统上的“对象哈希”是fd6988496e79a6a4bdb514a4655d2920209eb85d.

但是那个“对象哈希”到底是什么?这里散列的内容是什么?我们可以通过让 git 告诉我们有关该对象的更多信息来找出答案:

$ git cat-file -p fd6988496e79a6a4bdb514a4655d2920209eb85d
tree 30efc38ed890f113f9e1f0cbc801bab7090365eb
parent a99efa00891b66405ebd25e49868efc701fe1546
author Linus Torvalds <torvalds@linux-foundation.org> 1577662156 -0800
committer Linus Torvalds <torvalds@linux-foundation.org> 1577662156 -0800

Linux 5.5-rc4

上面的全部内容(格式略有不同)是我们得到 sha1 哈希的原因fd6988496e79a6a4bdb514a4655d2920209eb85d因此,到目前为止,我们已经从 Linus 的 PGP 签名到关于他的 git 存储库的另外两个重要部分进行了完整的加密证明:

  • 有关他的源代码状态的信息 ( tree)
  • 有关历史记录中上一次提交的信息 ( parent)
  • 关于提交的作者和提交者的信息,在这种特殊情况下是相同的
  • 有关提交的日期和时间的信息

让我们看一下这一tree行——什么内容被散列到了那个校验和?让我们问git:

$ git cat-file -p 30efc38ed890f113f9e1f0cbc801bab7090365eb
100644 blob 196ca317bd1f24ad57ad9ded549bc0b7994d8111    .clang-format
100644 blob 43967c6b20151ee126db08e24758e3c789bcb844    .cocciconfig
100644 blob a64d219137455f407a7b1f2c6b156c5575852e9e    .get_maintainer.ignore
100644 blob 4b32eaa9571e64e47b51c43537063f56b204d8b3    .gitattributes
100644 blob 72ef86a5570d28015d0ccb95ccd212bf8820c1c2    .gitignore
100644 blob a7bc8cabd157b89adbc2d8f6c4d6e3c88b14e3cd    .mailmap
100644 blob da4cb28febe66172a9fdf1a235525ae6c00cde1d    COPYING
100644 blob 9602b0fa1c958da4b605127c2b8da0628efeb34e    CREDITS
040000 tree b239b5eaacf2619bf564d152661ee425c4ee76f9    Documentation
...
040000 tree 82dd6833b421625c7b15d4d1c26964fc65874eb4    virt

这是顶级 Linux 内核目录内容的全部内容。这些blob条目是该目录中实际文件内容的 sha1sum,所以这些很简单。子目录表示为其他tree项目,这也包括blobtree记录会一路下滑到最后分段,这将只包含斑点。

因此,tree 30efc38ed890f113f9e1f0cbc801bab7090365eb提交记录中是其他校验和的校验和,它允许我们验证其中的每个文件都与linux.gitLinus Torvalds 创建提交时系统上的文件完全相同。如果更改了任何文件,则树校验和将不同,并且整个存储库将被视为无效,因为对象哈希将与提交中的不同。

最后,如果我们查看 中提到的对象parent a99efa00891b66405ebd25e49868efc701fe1546,我们会看到它是另一个提交的哈希,包含它自己的treeparent记录。如果我们愿意,我们可以将每个提交一直追溯到 Linux git 历史的开头,但我们不需要这样做——验证最新提交的校验和足以为我们提供所有必要的保证那棵树的全部历史。

因此,如果我们验证标签上的签名并确认它与属于 Linus Torvalds 的密钥匹配,我们将拥有强大的加密保证,即我们磁盘上的存储库与计算机上的存储库逐字节完全相同属于 Linus Torvalds——它的所有内容和整个历史都可以追溯到最初的提交。

由于您专门询问了签署提交而不是签署标签,因此我不得不提一下,PGP 签署提交通常是一种很好的做法,特别是在多人可以推送到同一个存储库分支的环境中。签名提交提供了代码来源的简单取证证明(例如,没有提交签名,Alice 可以伪造提交以假装它实际上是由 Bob 创作的)。它还允许在有人想要在不执行 git 合并的情况下将特定提交挑选到自己的树中的情况下轻松验证。

如果您想开始使用 git 和 PGP 签名,我可以在这里推荐我的指南:https ://github.com/lfit/itpol/blob/master/protecting-code-integrity.md

重要提示:如今,sha1 被认为不足以用于散列目的,这已被 git 开发社区广泛认可。将 git 迁移到更强大的加密散列的重大努力正在进行中,但它们需要仔细规划和实施,以尽量减少对使用 git 的各种项目的干扰。据我所知,没有 git 使用的针对 sha1 的有效攻击,并且 git 开发人员在 git 本身中添加了针对 sha1 冲突攻击的进一步预防措施,这有助于赢得一些时间,直到准备好更强大的哈希实现。