GPG-无需创建信任链即可验证签名?

GPG-无需创建信任链即可验证签名?

是否可以让 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

相关内容