![GPG-无需创建信任链即可验证签名?](https://linux22.com/image/1376429/GPG-%E6%97%A0%E9%9C%80%E5%88%9B%E5%BB%BA%E4%BF%A1%E4%BB%BB%E9%93%BE%E5%8D%B3%E5%8F%AF%E9%AA%8C%E8%AF%81%E7%AD%BE%E5%90%8D%EF%BC%9F.png)
是否可以让 gpg(或 gpg4win)仅验证文件是否由特定公钥文件签名,而不必导入、签名和信任该密钥?
例如
gpg --using-key pubkey.txt --verify message.txt
而不是必须创建自己的私钥然后执行
gpg --import pubkey.txt
gpg --lsign-key [name within pubkey.txt]
# ... something to do with choosing trust levels
gpg --verify message.txt
答案1
您必须拥有公钥才能验证使用相应私钥所做的签名,但您不必签名,甚至不必在本地签名密钥。在这种情况下,您将收到 GPG 发出的警告,提示您密钥不受信任。
这是我使用自己的密钥签名的文件所做的测试,但在尚未导入密钥的系统上:
[ben@seditious tmp]$ gpg -v --verify thing.txt.gpg
gpg: original file name='thing.txt'
gpg: Signature made Thu 26 Sep 2013 06:51:39 AM EST using RSA key ID 35C7553C
gpg: Can't check signature: public key not found
[ben@seditious tmp]$ gpg -v --status-fd 1 --verify thing.txt.gpg
gpg: original file name='thing.txt'
gpg: Signature made Thu 26 Sep 2013 06:51:39 AM EST using RSA key ID 35C7553C
[GNUPG:] ERRSIG 7FF2D37135C7553C 1 10 00 1380142299 9
[GNUPG:] NO_PUBKEY 7FF2D37135C7553C
gpg: Can't check signature: public key not found
[ben@seditious tmp]$
不幸的是,哈利的建议并没有奏效,它确实提取了更多的信息,但不足以发挥作用。
如您所见,获取的最多信息是用于进行签名的子密钥的密钥 ID 以及进行签名的时间。这与 pgpdump(或 --list-packets)可用的数据相匹配:
bash-3.2$ pgpdump thing.txt.gpg
Old: Compressed Data Packet(tag 8)
Comp alg - ZLIB <RFC1950>(comp 2)
Old: One-Pass Signature Packet(tag 4)(13 bytes)
New version(3)
Sig type - Signature of a binary document(0x00).
Hash alg - SHA512(hash 10)
Pub alg - RSA Encrypt or Sign(pub 1)
Key ID - 0x7FF2D37135C7553C
Next packet - other than one pass signature
Old: Literal Data Packet(tag 11)(24 bytes)
Format - binary
Filename - thing.txt
File modified time - Thu Sep 26 06:51:39 EST 2013
Literal - ...
Old: Signature Packet(tag 2)(412 bytes)
Ver 4 - new
Sig type - Signature of a binary document(0x00).
Pub alg - RSA Encrypt or Sign(pub 1)
Hash alg - SHA512(hash 10)
Hashed Sub: signature creation time(sub 2)(4 bytes)
Time - Thu Sep 26 06:51:39 EST 2013
Sub: issuer key ID(sub 16)(8 bytes)
Key ID - 0x7FF2D37135C7553C
Hash left 2 bytes - f0 97
RSA m^d mod n(3066 bits) - ...
-> PKCS-1
bash-3.2$
如您所见,它提供了哈希算法、密钥类型的详细信息(我的签名密钥是 3072 位 RSA 子密钥)以及子密钥的密钥 ID,但没有任何可以识别主密钥的信息。只有当您拥有公钥并验证签名时,才会显示该信息。
然后我在该系统上导入了我的公钥并再次尝试:
[ben@seditious tmp]$ gpg -v --verify thing.txt.gpg
gpg: original file name='thing.txt'
gpg: Signature made Thu 26 Sep 2013 06:51:39 AM EST using RSA key ID 35C7553C
gpg: using subkey 35C7553C instead of primary key 73590E5D
gpg: using PGP trust model
gpg: Good signature from "Ben M <ben@REDACTED>"
gpg: aka "Ben M <ben.m@REDACTED>"
gpg: aka "Ben M <ben.m@REDACTED>"
gpg: aka "Ben M (backup email address) <benm@REDACTED>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: DB47 24E6 FA42 86C9 2B4E 55C4 321E 4E23 7359 0E5D
Subkey fingerprint: B7F0 FE75 9387 430D D0C5 8BDB 7FF2 D371 35C7 553C
gpg: binary signature, digest algorithm SHA512
[ben@seditious tmp]$
现在它能够识别密钥并将其与主密钥匹配。但是,可以像这样减少这些警告的性质:
[ben@seditious tmp]$ gpg -v --verify --trust-model always thing.txt.gpg
gpg: original file name='thing.txt'
gpg: Signature made Thu 26 Sep 2013 06:51:39 AM EST using RSA key ID 35C7553C
gpg: using subkey 35C7553C instead of primary key 73590E5D
gpg: Good signature from "Ben M <ben@REDACTED>"
gpg: aka "Ben M <ben.m@REDACTED>"
gpg: aka "Ben M <ben.m@REDACTED>"
gpg: aka "Ben M (backup email address) <benm@REDACTED>"
gpg: WARNING: Using untrusted key!
gpg: binary signature, digest algorithm SHA512
[ben@seditious tmp]$
仍然有警告表明这是一个不受信任的密钥,但警告并不严重,删除冗长的内容只会将其减少到这样:
[ben@seditious tmp]$ gpg --verify --trust-model always thing.txt.gpg
gpg: Signature made Thu 26 Sep 2013 06:51:39 AM EST using RSA key ID 35C7553C
gpg: Good signature from "Ben M <ben@REDACTED>"
gpg: aka "Ben M <ben.m@REDACTED>"
gpg: aka "Ben M <ben.m@REDACTED>"
gpg: aka "Ben M (backup email address) <benm@REDACTED>"
gpg: WARNING: Using untrusted key!
[ben@seditious tmp]$
验证阶段需要公钥,因为它用于将签名者生成的数据与私钥进行匹配。简单地说,公钥可以看作是加密的补充,其中需要私钥来解密使用公钥加密的数据。
注意:我在此示例中对 UID 做了一些调整,但每个获得该密钥的人都会看到它们的真实身份。否则,输出就是直接复制和粘贴。
编辑:如果您拥有非 ASCII 装甲格式(即 .gpg 文件而不是 .asc 文件),则可以像密钥环一样直接调用公钥文件。即便如此,您仍然需要公钥。要执行此操作,命令如下:
[ben@seditious ~]$ gpg -v --no-default-keyring --keyring /tmp/mykey.gpg --verify /tmp/thing.txt.gpg
gpg: original file name='thing.txt'
gpg: Signature made Thu 26 Sep 2013 06:51:39 AM EST using RSA key ID 35C7553C
gpg: using subkey 35C7553C instead of primary key 73590E5D
gpg: using PGP trust model
gpg: Good signature from "Ben M <ben@REDACTED>"
gpg: aka "Ben M (backup email address) <benm@REDACTED>"
gpg: aka "Ben M <ben.m@REDACTED>"
gpg: aka "Ben M <ben.m@REDACTED>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: DB47 24E6 FA42 86C9 2B4E 55C4 321E 4E23 7359 0E5D
Subkey fingerprint: B7F0 FE75 9387 430D D0C5 8BDB 7FF2 D371 35C7 553C
gpg: binary signature, digest algorithm SHA512
[ben@seditious ~]$
答案2
如果您同意发送密钥环而不是公钥文件,那么您可能想要使用gpgv
而不是gpg
:
gpgv --keyring key.ring somefile.txt
答案3
如果问题中的“验证”一词表示“绝对验证”,那么当然必须导入公钥才能完全验证已签名的文档。但是,如果这意味着“识别”,那么我下面将介绍一种启发式方法,它可以判断一组文档是否全部由同一签名签名。
根据由@Ben 进行的测试为了验证我的评论,有可能使用以下命令来启发式地指示签名密钥:
gpg --status-fd 1 --verify thefile.gpg
Ben 的测试结果如下。值得注意的是 ERRSIG 和 NO_PUBKEY 的值,以及部分包含在它们中的“RSA key ID”的值,如下所示:
[ben@seditious tmp]$ gpg -v --status-fd 1 --verify thing.txt.gpg
gpg: original file name='thing.txt'
gpg: Signature made Thu 26 Sep 2013 06:51:39 AM EST using RSA key ID 35C7553C
[GNUPG:] ERRSIG 7FF2D37135C7553C 1 10 00 1380142299 9
[GNUPG:] NO_PUBKEY 7FF2D37135C7553C
gpg: Can't check signature: public key not found
注意上面的字符串7FF2D37135C7553C
。导入密钥后报告的密钥指纹中也会发现相同的字符串:
[ben@seditious ~]$ gpg -v --no-default-keyring --keyring /tmp/mykey.gpg --verify /tmp/thing.txt.gpg
gpg: original file name='thing.txt'
gpg: Signature made Thu 26 Sep 2013 06:51:39 AM EST using RSA key ID 35C7553C
gpg: using subkey 35C7553C instead of primary key 73590E5D
gpg: using PGP trust model
gpg: Good signature from "Ben M <ben@REDACTED>"
gpg: aka "Ben M (backup email address) <benm@REDACTED>"
gpg: aka "Ben M <ben.m@REDACTED>"
gpg: aka "Ben M <ben.m@REDACTED>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: DB47 24E6 FA42 86C9 2B4E 55C4 321E 4E23 7359 0E5D
Subkey fingerprint: B7F0 FE75 9387 430D D0C5 8BDB 7FF2 D371 35C7 553C
gpg: binary signature, digest algorithm SHA512
此字符串位于指纹(上面的子密钥)的下部,因此可能用于识别密钥。除了子密钥之外,可能还应验证“主密钥指纹”。
“RSA key ID”字符串在两个输出中是相同的,并且也是指纹的最后一部分,因此它本身可能足以识别签名。如果是这样的话,仅使用的输出可能就足以以更gpg --verify
简单的方式识别签名。
[ben@seditious tmp]$ gpg -v --verify thing.txt.gpg
gpg: original file name='thing.txt'
gpg: Signature made Thu 26 Sep 2013 06:51:39 AM EST using RSA key ID 35C7553C
gpg: Can't check signature: public key not found
我对 GPG 的了解不足以完全验证此方法,因此您应该在更多示例文件上尝试此方法。如果有效,您可以根据文件的签名对它们进行排序,但需要导入密钥才能找到签名者的身份。
再次明确说明:此方法无法完全识别签名。它只是一种启发式排序签名文件的方法。
答案4
我最终在这里寻找一种在 apt 之外验证 InRelease 文件的方法
这就是我现在拥有的:
for i in /etc/apt/trusted.gpg.d/*.gpg; do
[[ $trusted -eq 0 ]] && gpg --status-fd 1 --no-random-seed-file --homedir . --no-default-keyring --trust-model always --keyring $i --verify InRelease 2>/dev/null | grep -q GOODSIG && trusted=1
done