システム構成管理ツールのいくつかの側面を検証するためにgpg署名を使用したいと思います。さらに、個々のsysadminキーがマスター署名キーで署名される「信頼」モデルを使用したいと考えています。その後、システムはそのマスターキーを信頼します(そして、sysadminによる署名を検証するために「web of trust」を使用します)。
これにより、誰かが離れたときにキーの信頼を簡単に取り消すことができるなど、多くの柔軟性が得られますが、問題が発生しました。 gpg
コマンドはtellを実行しますが、キーが信頼できない場合は、このことを示す終了コードを返しません。例えば:
# 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 <[email protected]>"
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
はキーサーバーからキーを取得する方法を知りません。 gpg
からのステータス出力(--status-fdを使用)を解析できると思いますが、もっと良い方法はありますか?
これは、次のようになったものです。
#!/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 <[email protected]>"
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
だから問題を分割してみましょう:
最初の問題は、あなたがテストしているキーが信頼されていないようです。
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 <[email protected]>"
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
これは意図的なものだと思っていました...しかし、修正する前に、gpg -vの代わりにgpgvを使用することをお勧めしますか?すぐに理由がわかります。
$ 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 <[email protected]>" 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 <[email protected]>"
$ echo $?
0
それが役に立てば幸い
2つのオプションが思い浮かびます(出力の解析以外)。
すばやく汚れた方法は、bothgpg
とgpgv
の両方を実行することです。 gpg
を最初に実行すると、キーがキーサーバーから確実にフェッチされ、次にgpgv
で必要な戻りコードが返されます。
よりエレガントで制御された方法(より多くの作業が必要になります)は、署名を検証するために gpgme ライブラリーを使用することです。 Perl 、 [〜#〜] php [〜#〜] 、 Python および-のラッパーはありますが、これはCライブラリです。 ルビー 。 (Python 1つは非常に低いレベルですが、Ruby 1つはいくつかのより高いレベルの抽象化を持っていますが、PerlまたはPHPについては不明です)。
GPGMEライブラリは、私が使用したときにキーサーバーと通信しているように見えますが、確認する必要があります。 Ruby gpgmeライブラリを使用するコード (verify
とverified_ok?
を検索して、署名、およびsig_output_lines
の場合、署名が信頼できるかどうかを判断する一部のコード)。