1

我想知道 git 签名标签中究竟签署了什么。我们来分析一下 Linux v4.14-rc3 签名。

$ git show v4.14-rc3 | head -n 20
tag v4.14-rc3
Tagger: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Sun Oct 1 14:55:06 2017 -0700

Linux 4.14-rc3
-----BEGIN PGP SIGNATURE-----

iQEcBAABAgAGBQJZ0WQ6AAoJEHm+PkMAQRiGuloH/3sF4qfBhPuJo8OTf0uCtQ18
4Ux9zZbm81df/Jjz0exAp1Jqk+TvdIS3OXPWcKilvbUBP16hQcsxFTnI/5QF+YcN
87aNr+OCMJzOBK4suN1yhzO46NYHeIizdB0PTZVL1Zsto69Tt31D8VJmgH6oBxAw
Isb/nAkOr31dZ9PI5UEExTIanUt6EywVb0UswA+2rNl3h1UkeasQCpMpK2n6HBhU
kVD7sxEd/CN0MmfhB0HrySSam/BeSpOtzoU9bemOwrU2uu9+5+2rqMe7Gsdj4nX6
3Kk+7FQNktlrhxCZIFN/+CdusOUuDd8r/75d7DnsRK5YvSb0sZzJkfD3Nba68Ms=
=7J2+
-----END PGP SIGNATURE-----

commit 9e66317d3c92ddaab330c125dfe9d06eee268aff
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Sun Oct 1 14:54:54 2017 -0700

这个 GPG 签名可以解码为:

Old: Signature (Tag 2)
Version: 4
Signature Type: Signature of a binary document. (type 0x00)
Public Key Algorithm: RSA (Encrypt or Sign) (pka 1)
Hash Algorithm: SHA1 (hash 2)
Hashed Sub:
    Signature Creation Time Subpacket (sub 2) (4 octets)
        Creation Time: Sun Oct 1 21:55:06 UTC 2017
Unhashed Sub:
    Issuer Subpacket (sub 16) (8 octets)
        Key ID: 79be3e4300411886
Hash Left 16 Bits: ba5a
RSA m**d mod n (2047 bits): 7b05e2a7c184fb89a3c3937f4b82b50d7ce14c7dcd96e6f3575ffc98f3d1ec40a7526a93e4ef7484b73973d670a8a5bdb5013f5ea141cb311539c8ff9405f9870df3b68dafe382309cce04ae2cb8dd728733b8e8d6077888b3741d0f4d954bd59b2da3af53b77d43f15266807ea807103022c6ff9c090eaf7d5d67d3c8e54104c5321a9d4b7a132c156f452cc00fb6acd97787552479ab100a93292b69fa1c18549150fbb3111dfc23743267e10741ebc9249a9bf05e4a93adce853d6de98ec2b536baef7ee7edaba8c7bb1ac763e275fadca93eec540d92d96b87109920537ff8276eb0e52e0ddf2bffbe5dec39ec44ae58bd26f4b19cc991f0f735b6baf0cb

79be3e4300411886 密钥公共模数和指数是:

modulus=0xa49fe68e2e6b1aab57a351c5c200e5e43b7c3b7a22ea8d1ff38932f6299df4a7b6f13fc713517bdf33b7f013b127a820a48e2db9c76c6ca0a5c1f00954b302046141423aea63d813ac56627faca656edf0af29338af8182e2a379b0f135b82689fdfd6df4a71c35ab5bcdf67f91eb626667edafd5c920d015dba5f0697f47a82ce8f1c96e08e3b7e2bb3f1e9c41531536f63f54159dbc0d737243bfe21ea07f791659937e5a5abcc2ffe9c5fb7c433345830787f68e5b8f8b6743ec0c08b08b883b2012e55ac28380920ddd44cba0214a222a804ac3b6f6d6af558e9e237b346f7220ba62ce241944851b5663227dcca58ddfdf1677cae630af143c25c03b293
e=0x010001

使用 python pow() 函数我们得到:

sig = 0x7b05e2a7c184fb89a3c3937f4b82b50d7ce14c7dcd96e6f3575ffc98f3d1ec40a7526a93e4ef7484b73973d670a8a5bdb5013f5ea141cb311539c8ff9405f9870df3b68dafe382309cce04ae2cb8dd728733b8e8d6077888b3741d0f4d954bd59b2da3af53b77d43f15266807ea807103022c6ff9c090eaf7d5d67d3c8e54104c5321a9d4b7a132c156f452cc00fb6acd97787552479ab100a93292b69fa1c18549150fbb3111dfc23743267e10741ebc9249a9bf05e4a93adce853d6de98ec2b536baef7ee7edaba8c7bb1ac763e275fadca93eec540d92d96b87109920537ff8276eb0e52e0ddf2bffbe5dec39ec44ae58bd26f4b19cc991f0f735b6baf0cb
print hex(pow(sig,e,modulus))
0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414ba5aef12cc8a6983ff47f16a515b1da496a39822L

签名中的 ASN.1 输出表示 sha1 (1.3.14.3.2.26),哈希为ba5aef12cc8a6983ff47f16a515b1da496a39822. 哪些输入数据散列到该值?我希望 shell oneliner 在 Linux 内核 git 存储库中执行时会输出此值。

4

2 回答 2

1

哪些输入数据散列到该值?

这些Documentation/technical/signature-format.txt. 输入是标签中的所有内容(例如,git cat-file -p <tag-specifier>),除了切割线之间的部分——这个例外包括切割线本身。此外,-----BEGIN PGP SIGNATURE-----应该在标签的末尾,这样从这里删除到末尾就足够了;几个 shell 脚本,例如contrib/examples/verify-tag.sh,简单地退出sed以剥离签名以进行验证。

我会很感激shell oneliner,它会输出[未签名的标签]

git-verify-tag.sh 代码有一些,但我会在这里复制粘贴:

trap 'rm -f "$GIT_DIR/.tmp-vtag"' 0

git cat-file tag "$1" >"$GIT_DIR/.tmp-vtag" || exit 1
sed -n -e '
        /^-----BEGIN PGP SIGNATURE-----$/q
        p
' <"$GIT_DIR/.tmp-vtag" |
gpg --verify "$GIT_DIR/.tmp-vtag" - || exit 1
rm -f "$GIT_DIR/.tmp-vtag"

将其中的一部分转换为一行非常容易,因为sed将从管道中读取。

于 2017-10-02T15:20:28.417 回答
0

签名格式的描述最近(2021 年第四季度)随着 Git 2.34 的发展而演变:

请参阅Junio C Hamano ( ) 的提交 f6c013d(2021 年 10 月 12 日(由Junio C Hamano 合并——提交 97ab03b中,2021 年 10 月 25 日)gitster
gitster

signature-format.txt: 解释和说明多行标题

报告人:Rob Browning

附加到已签名提交的签名以及合并已签名标签的提交的内容都被记录为作为多行值的对象头字段的值,并且受多行值的格式约定的约束在标题中,前导 SP 表示该行的其余部分是前一行的延续。
最值得注意的是,这种多行值中的空行将导致一行具有唯一的 SP。

签名格式技术文档中的示例包括其中一些案例,但我们没有在示例中显示这些原本不可见的 SP。
这些尾随空格在显示器或纸上看不到,并且迫使读者在他们的编辑器或寻呼机中查找它们,即使我们将它们添加到文档中也是如此。

扩展概述部分以解释多行值格式,并通过发明“在 SP 之后出现的行尾的美元符号仅表示那里有一个 SP,以及美元符号本身”来突出这些原本不可见的 SP没有出现在真实文件中”符号,受“ cat -e”输出的启发,以帮助读者准确了解示例中出现的“单个 SP 最初是空行”的位置。

technical/signature-format现在在其手册页中包含:

签名有时会作为正常负载的一部分出现(例如,签名标签在签名适用的负载之后附加签名块),有时会出现在对象标头的值中(例如,合并签名标签的合并提交将在其“mergetag”标头上包含整个标签内容)。在后者的情况下,适用于对象标题的常用多行格式规则。即,第二行和后续行以 SP 为前缀,表示该行是从前一行继续的。

甚至对于最初为空的行也是如此。在以下示例中,以空格字母结尾的行尾用$符号突出显示;如果您尝试手动重新创建这些示例,请不要剪切和粘贴它们——它们主要是为了突出显示某些行末尾的额外空白。

于 2021-12-05T03:05:47.870 回答