用gpg验证签名信任吗?


13

我们想使用gpg签名来验证我们的系统配置管理工具的某些方面。此外,我们希望使用“信任”模型,其中,使用主签名密钥对单个sysadmin密钥进行签名,然后我们的系统信任该主密钥(并使用“信任网络”来验证sysadmin的签名)。

这给了我们很大的灵活性,例如当有人离开时可以轻松地撤消对密钥的信任,但是我们遇到了问题。虽然该gpg命令将告诉您密钥是否不受信任,但它似乎未返回指示此事实的退出代码。例如:

# gpg -v < foo.asc
Version: GnuPG v1.4.11 (GNU/Linux)
gpg: armor header: 
gpg: original file name=''
this is a test
gpg: Signature made Fri 22 Jul 2011 11:34:02 AM EDT using RSA key ID ABCD00B0
gpg: using PGP trust model
gpg: Good signature from "Testing Key <someone@example.com>"
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: ABCD 1234 0527 9D0C 3C4A  CAFE BABE DEAD BEEF 00B0
gpg: binary signature, digest algorithm SHA1

我们关心的部分是这样的:

gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.

尽管信任失败,在这种情况下gpg返回的退出代码为0:

# echo $?
0

如果使用不可信的签名进行签名,我们如何使gpg失败?

我已经看到一些建议,该gpgv命令将返回正确的退出代码,但是不幸的gpgv是,它不知道如何从密钥服务器获取密钥。我猜我们可以解析来自的状态输出(使用--status-fd)gpg,但是还有更好的方法吗?

Answers:


6

结果是:

#!/bin/sh

tmpfile=$(mktemp gpgverifyXXXXXX)
trap "rm -f $tmpfile" EXIT

gpg --status-fd 3 --verify "$@" 3> $tmpfile || exit 1
egrep -q '^\[GNUPG:] TRUST_(ULTIMATE|FULLY)' $tmpfile

这寻找在上gpg输出的信任信息--status-fd。在存在不受信任的签名(或无效/无签名)的情况下,脚本退出并出现错误:

$ sh checksig sample.sh.bad 
gpg: Signature made Mon 24 Jun 2013 11:42:58 AM EDT using RSA key ID DCD5C569
gpg: Good signature from "Test User <testuser@example.com>"
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: 6FCD 3CF0 8BBC AD50 662E  5070 E33E D53C DCD5 C569
$ echo $?
1

在存在有效的,受信任的签名的情况下,脚本将正确退出:

$ sh checksig sample.sh.good
gpg: Signature made Mon 24 Jun 2013 11:38:49 AM EDT using RSA key ID 5C2864A8
gpg: Good signature from "Lars Kellogg-Stedman <...>"
$ echo $?
0

5

因此,让我尝试拆分问题:

第一个问题似乎是您所测试的密钥是不可信的。

gpg -v < test.txt.asc 
gpg: armor header: Version: GnuPG v1.4.11 (GNU/Linux)
gpg: original file name='test.txt'
this is a test
gpg: Signature made Thu 11 Aug 2011 09:09:35 PM EST using RSA key ID FE1B770E
gpg: using PGP trust model
gpg: Good signature from "John Doe <jdoe@noemail.com>"
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: 5DD8 216D ADB1 51E8 4326  3ACA 1DED BB72 FE1B 770E
gpg: binary signature, digest algorithm SHA1

我以为这是故意的...但是在开始解决之前,让我建议您使用gpgv而不是gpg -v?一分钟后,您将明白为什么:

$ gpgv < test.txt.asc 
gpgv: keyblock resource `/user/.gnupg/trustedkeys.gpg': file open error
gpgv: Signature made Thu 11 Aug 2011 09:09:35 PM EST using RSA key ID FE1B770E
gpgv: Can't check signature: public key not found

$ echo $?
2

没有密钥,没有信任...不,我们将密钥导入trustedkeys.gpg

$ gpg --no-default-keyring --keyring trustedkeys.gpg --import jdoe_pub.gpg
gpg: keyring `/user/.gnupg/trustedkeys.gpg' created
gpg: key FE1B770E: public key "John Doe <jdoe@noemail.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
$ gpgv < test.txt.asc 
gpgv: Signature made Thu 11 Aug 2011 09:09:35 PM EST using RSA key ID FE1B770E
gpgv: Good signature from "John Doe <jdoe@noemail.com>"

$ echo $?
0

希望能帮助到你


我在问题中对gpgv进行了评论-gpgv的问题在于,尽管它确实返回了更有用的错误代码,但它不知道如何从密钥服务器获取密钥。
larsk

1

我想到两个选项(解析输出除外)。

一个快速和肮脏的方法是运行 gpggpgv。的第一次运行gpg将确保从密钥服务器获取密钥,然后gpgv将为您提供所需的返回码。

一种更优雅,可控制的方式(尽管这会涉及更多工作)是使用gpgme库来验证签名。尽管有PerlPHPPythonRuby的包装器,但它是一个C库。(Python的级别很低,而Ruby的级别更高,不确定Perl或PHP)。

尽管我想确认一下,但GPGME库在我使用它时似乎正在与密钥服务器对话。我编写了一些使用ruby gpgme库代码(搜索verifyverified_ok?验证签名的代码,以及sig_output_lines一些确定签名是否受信任的代码)。


-1

将系统配置迁移到Puppet或Chef之类的工具怎么样?

虽然工作量不大,但Chef(我还没有使用Puppet)必须创建用户帐户(并生成发布/私有密钥)。虽然这不会阻止人们修改服务器上的本地文件,但是Chef-client会定期运行,并在下次运行时覆盖其更改。(默认情况下会定期进行定期运行。)

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.