使用 GPG 签署 git 提交时,究竟签署了什么?

问题描述

如果我使用 GPG 签署提交(https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work),然后检查我刚刚创建的提交对象的内容

git commit -a -S -m "This is a Signed commit"
git cat-file -p HEAD

我明白了:

tree 1265193cc831c2bd47cedbb27f029e5d45fa0bb039d5bb5136f152a3e88c07b0
parent 16625976433ec56a26feb1478051b28b78684a3d68f475221afcfae2a7aaaa0d
author John Doe <john.doe@internet.www> 1612379624 +0100
committer John Doe <john.doe@internet.www> 1612379624 +0100
gpgsig-sha256 -----BEGIN PGP SIGNATURE-----

 iQGzBAABCAAdFiEELgGt+L8yg4keIDJDpyYj1XHdLa8FAmAa9egACgkQpyYj1XHd
 La+BogwA0VEoobCJPRLk2olHzW6iO9ioyxIrrW6uPAcLv6uernxrGDK6odYuywED
 XeVEu3L9/HLG8MYSqgAGKDWfiOphRi5Lw1fLnSA3MNC1uh18OqdmD/PjyP9hMnbC
 XayugJJ2dPkUHADxeDoQOGHg6wmfn+/4IsHit74YsAYXcDz1/QIHrEGMPCwROGCX
 Nb1srMw2/8e+NM9U5h5KSw5ZYmBtSynIWCsHBC2w8eqvuhKMmKxbGV3izV7eOTfl
 R8aC2FJSuSd/MhGprAki2sW1efiNr1EJNt/hvP2S9Eq/fkLUlVuWk5cyg/8tDJX5
 VQO5RqCTR/Yz5mleoKMOeBBARzWK/r1l0bVQZYoraO8I8zxuLt5gkxqvqTOrhOKy
 uTX58BdQHSlx1fU02UuPruimpbSZOBhwPFeVXl8Kj3zUWLNpTeQXZ/MSNZOiR1qF
 xMdqKbuzh53B3tqvd02Cy7jdisst8DwLM5V3IjYfv/GG/iQOE7BHGxYbPgEkv4e6
 KvUBxEjj
 =8gBZ
 -----END PGP SIGNATURE-----

This is a Signed commit

正在签署的摘要究竟是什么?如果签名嵌入在提交对象中,那么它几乎不可能是提交哈希本身 - 那么它是树哈希吗?或者是其他东西? 这是否意味着提交消息没有签名并且可能被篡改?

注意:我在这里使用了一个使用 --object-type sha256 初始化的 git 存储库以使用基于 SHA-256 的哈希(认情况下 git 使用 SHA-1),但我的问题适用于带有 SHA- 的 git 存储库1 哈希(以防 gpg 签名对 SHA-1 和 SHA-256 存储库的工作方式不同)

解决方法

您签名的数据是整个提交或标签对象,减去任何以 gpgsig 开头的多行标头的内容,以及在标签的情况下,尾随标签的内容签名。所以,基本上是对象的内容减去签名部分本身。这包括消息。

请注意,对象的哈希包括签名,因此除非您重写历史记录,否则无法删除或更改(或添加其他签名)签名。

Git 2.30 和之前的版本有一个错误,他们会错误地将具有多个签名的提交或标记标记为无效。下一个版本可能会包含一个补丁来解决这个问题。

如果将没有签名部分的提交放入名为 commit 的文件中,并将签名部分(减去前导空格)放入名为 commit.asc 的文件中,则可以使用 {{ 1}}。