如何使用gpg验证加密和签名的文件?

20

我想更好地理解gpg的工作原理。

如果你有一个文件并对其进行签名:gpg --sign file.txt

你可以使用以下命令验证它:gpg --verify file.txt.gpg

当你得到成功的输出时:gpg: Signature made...

但是,当你对文件进行签名和加密时:gpg --encrypt --sign -r test@email.com file.txt

然后在加密文件上运行--verify, 我得到:gpg: verify signatures failed: Unexpected error

我知道我可以通过调用--decrypt来验证并解密文件,但如果我只想要验证怎么办?

4个回答

27
我已经找到了答案,而且还有一些额外的信息需要说明。
首先,根据最后一行所说的这个答案,我意识到gpg使用的是签名再加密的方式。这意味着调用--verify或其任何变体来验证一个加密文件将只会输出gpg: verify signatures failed: Unexpected error。这是因为在加密中“隐藏”了签名,所以当您尝试在文件上调用--verify时,它将看不到签名。
其次,--decrypt标志将同时解密文件并验证文件签名(如果存在)。
以下是--decrypt的操作。它查看您默认的保密密钥环secring.kbx~/.gnupg中使用密钥解密文件。然后,在文件解密后,它查看您默认的公钥环pubring.kbx在文件夹~/.gnupg中,并尝试验证文件上的签名(如果有的话)。
  • 如果文件没有签名,则它只会对文件进行解密。

  • 如果文件有签名但是您没有公钥,则它将对文件进行解密,但无法验证签名。

  • 如果文件有签名并且您有公钥,则它将解密并验证文件。

因此,在解密文件之前,没有理由验证已签名的文件。

第三,额外的好处是,您还可以指定要用于解密和验证的密钥环。例如,您想使用临时密钥环验证签名或因为某种原因需要使用临时密钥环来解密消息。

您可以使用以下命令为--decrypt指定要使用的密钥环:

gpg --secret-keyring path/to/temp/secring.kbx --keyring path/to/temp/pubring.kbx --decrypt file.txt.gpg

此命令将在指定路径中查找秘密环和公共环,以便使用这些环进行解密和验证,而不是使用~/.gnupg中找到的默认环。想要使用临时环和默认环?只需省略标志和默认环的路径即可。

总的来说,对于加密和签名的文件,如果您想解密和验证该文件,则需要确保您的私钥用于解密在您的私钥环中,而验证所需的公钥在您的公钥环中。


1
感谢您的回答。但是需要指出的是,即使您没有公钥,gpg仍会尝试验证签名,并以非零退出代码失败。 - Cyker
1
如果它具有签名但您没有私钥,则应更正为:如果它具有签名,但您没有公钥... - Shuzheng
这个答案看起来有点危险。虽然它正确地说明了签名加密文件也将作为副作用进行验证,但未签名的加密文件呢?验证阶段将被静默跳过,并使用未经验证的文件,对吗? - Pavel Šimerda

4

关于GPG加密与签名,需要理解的一件事情是,签名只能由接收者验证,这一点并没有得到很好的解释。

假设Alice要将一个文件加密并发送给Bob,她会使用Bob的公钥进行加密,并用自己的私钥进行签名。

gpg --output encrypted.gpg --recipient B0B0000000000000000000000000000000000000 --armor --sign --default-key A11CE00000000000000000000000000000000000 --encrypt file-to-encrypt.txt

现在Alice或任何没有Bob的私钥的人都无法验证签名。

现在Bob将解密文件。如果文件有签名,他就会在输出中看到关于签名的信息:

$ gpg --decrypt encrypted.gpg > decrypted.txt
gpg: encrypted with 2048-bit RSA key, ID D83A4C12B3840EBA, created 2020-09-24
      "Alice <alice@example.com>"
gpg: Signature made 09/28/20 13:16:47 Eastern Daylight Time
gpg:                using RSA key A11CE00000000000000000000000000000000000 
gpg: Good signature from "Alice <alice@example.com>" [ultimate]

请注意输出中的Signature madeGood signature行。

任何拥有公钥的人都可以验证签名。这就是公钥基础设施的全部意义。私钥可以签名,公钥可以加密。文件只能由拥有与加密文件所使用的公钥相对应的私钥的人解密。如果使用GnuPG首先对文件进行签名,然后再进行加密,显然谁可以做什么取决于顺序。如果需要先解密文件,则需要拥有私钥,只有在此之后才能使用发送者的公钥验证签名。 - Thomas Seeling

1

我知道我来晚了几年。

你知道gpg--decrypt操作,在这种情况下是"解密并验证"消息。你在answer中也很好地解释了所需的密钥。

为了确认这个两步过程,可以通过一步来完成。

gpg -vi  --output signed.gpg    --unwrap  signed_and_encoded.gpg 

这一步是解密,也就是第一步。

生成的文件现在已经解码并包含了签名。

这表明使用gpg --sign --encrypt file生成的产品在没有解密的情况下无法验证,但可以在没有(尚未)验证的情况下解密。解密后的文件可以稍后通过gpg -d进行验证(和显示),只需要发送者的公钥。

更多信息和文档链接可以在我的回答这里找到。


这个方法是有效的,也是一个有趣的观点,但是它会发出警告:“gpg: 警告:未提供命令。尝试猜测你的意思...” 你知道应该使用哪个命令吗? - Max Murphy
1
@Max,1. 可能因版本不同而有所差异,所以需要小心处理。2. 在Ubuntu中没有记录这个文件,所以需要小心处理。3. 在互联网上说它是一个命令,这意味着它不应该抱怨(对于那个特定的版本)。4. 在本地环境中,在文件前面添加“-d”可以消除警告,但不会影响--unwrap操作。在您的机器上通过gpg测试输出文件,如果它仍然包含签名:gpg: Good signature from "tests..."。请注意。 - minorChaos

0
$ gpg --encrypt --sign -r test@email.com file.txt

在生成 file.txt.gpg 文件后,请尝试以下命令:

$ gpg -d file.txt.gpg

或者直接执行:

$ gpg file.txt.gpg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接