GPG-在不创建信任链的情况下验证签名?


19

是否可以要求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 --status-fd 1 --verify (thefile)在其输出中以第一个字符串形式给出进行签名的密钥的指纹。
harrymc 2013年

这里有一些上下文:我们有一个对事物进行签名的系统。我们将其公钥提供给可能从该系统接收消息的人员,以便他们可以检查消息是否被篡改。但是,我们不想告诉收件人“信任此密钥签名的任何内容 ”,因为这样它就可以用于对来自其他系统的消息进行身份验证(例如,来自其朋友的电子邮件)。
OJW

因此,我们想给某人一个命令/批处理文件,该文件检查“ gpg是否说此消息是通过此密钥发送的?” 而不会干扰他们日常使用gpg与他人交流。该密钥仅应受信任,因为命令行要求它,而不是因为已告知GPG始终信任该密钥。
OJW

Answers:


14

您必须具有公共密钥来验证使用相应的私有密钥进行的签名,但是您不必签名,甚至不必在本地签名。在这种情况下,您会收到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]$ 

不幸的是,Harry的建议没有用,它确实提取了更多信息,但不足以使用。

如您所见,获得的最多信息是用于进行签名的子项的密钥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 ~]$ 

查看您的输出,我得出了完全相反的结论。我在回答中使用了您的输出,但是对此表示赞赏。
harrymc

您所指的部分是子密钥的密钥ID的长格式(技术上完整的密钥ID 指纹)是唯一可识别的部分。但是,如果没有公共密钥,您将无法识别主密钥或验证签名。细节在RFC 4880的5.2节中(在2.2节中有一点点,但是5.2是有用的地方)。如果我错了,请在没有密钥副本的情况下证明验证(提示:您无法通过示例进行验证)。
2013年

此外,根据关于--verify的结论,它仅在密钥可用时才有效,否则请返回我的答案中的第一个示例,在该示例中验证了密钥ID和签名时间,但未找到密钥。
2013年

是的,仅凭钥匙ID当然不可能完全识别。我修改了答案,以明确声明这只是一种启发式方法。您的结论是,发帖人要问的是不可能的,但这可能是因为发帖人使用了“ verify”一词,该词太强了。
harrymc

1
没错,OP可能未正确使用这些术语,我可能也在几个地方捏造了这些术语(昨晚我打了很多喷嚏)。如果他的问题只是有关验证一个签名没有导入键,然后例如在我的编辑展示了如何可以做到的,但只有当该密钥是在OpenPGP的(pubkey.gpg)格式。如果导出的密钥为ASCII铠装(pubkey.asc)格式,则此方法无效。
2013年

2

如果您可以发送密钥环而不是公钥文件,则可能要使用gpgv而不是gpg

gpgv --keyring key.ring somefile.txt

0

如果问题中的“验证”一词表示“绝对验证”,那么当然必须导入公钥以完全验证签名的文档。但是,如果这意味着“标识”,那么我在下面描述一种启发式方法,该方法可以判断一组文档是否都由同一签名签名。

根据@Ben为验证我的评论而进行测试,有可能使用以下命令来启发式地指示签名密钥:

gpg --status-fd 1 --verify thefile.gpg

本的测试给出了以下结果。值得注意的是ERRSIG和NO_PUBKEY的值,以及部分包含在其中的“ RSA密钥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密钥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的了解不足以完全验证此方法,因此您应该在更多示例文件中尝试使用。如果可行,则可以根据文件的签名对文件进行排序,但是需要导入密钥以找到签署人的身份。

再次明确声明:此方法无法完全识别签名。这只是对签名文档进行启发式排序的一种方法。


签名包含足够的数据来标识用于创建它的密钥,并且可以与密钥服务器结合使用它来定位主密钥(假设在我的示例中使用了签名子密钥)。如果没有OpenPGP格式的公共密钥副本(无论是在密钥环中还是在我的最终示例中),就无法验证签名,因为指纹/密钥ID不足以计算出来。

@Ben:我再说一遍,这只是一种启发式方法,这是回答张贴者“验证文件是否由特定的公共密钥文件签名,而不必导入,签名和信任该密钥”问题的最佳方法。 ”。
harrymc

如果我说我们信任.pub文件中的任何密钥(出于检查此特定数据文件的目的),而我们选择信任此.pub文件的原因不在本文讨论范围之内,它将使这个问题更清楚了吗?任何GPG活动?
OJW

在.pub文件中列出密钥并比较其RSA密钥ID的试探法是否有用?我在这里没有gpg可以尝试,但是也许像“ gpg --no-default-keyring --keyring <pub-file> --list-keys”之类的东西。
harrymc
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.