Scripting with gpg

I have a build script that may, as a matter of convenience, download and build a third-party software package.  Before the build script goes into any release, I want to tighten up its security to ensure it verifies the PGP signature on the package.

OK, I can do that in a Makefile using two separate targets: the tarball, and the verified tarball.  I thought I could make the latter a link to the former, using something like:

gpg –verify $(TARBALL).asc $(TARBALL) \
&& ln $(TARBALL) $(TARBALL-VERIFIED) \
|| (echo “### Please verify $(TARBALL) ###” && exit 1)

However, this is failing me, because gpg is too trusting:

$ gpg –verify nginx-1.7.3.tar.gz.asc nginx-1.7.3.tar.gz
gpg: Signature made Tue 8 Jul 14:22:56 2014 BST using RSA key ID A1C052F8
gpg: Good signature from “Maxim Dounin <email.suppressed>”
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: B0F4 2533 73F8 F6F5 10D4 2178 520A 9993 A1C0 52F8

$ echo $?
0

(OK, now you know the identity of $(TARBALL))

It has not verified that the signature is trusted, but it still thinks all’s well.  Ouch!  I can verify the signature manually (if rather weakly) but I’d rather not try to script that.  Nor do I want to concern myself with issues that might change with each new nginx release, or with changes of pgp keys.

A bit of googling finds this message, from which it appears this was a known bug but fixed in GnuPG version 1.4.2.1 back in 2006 (and yes, my gpg version is more recent than that)!  Was that a non-fix that only tells you if it’s a BAD signature or no PGP data at all?  That would be no more useful than an MD5 or SHA checksum!

OK folks, what am I missing?  What do you use to script the verification of a package?

Posted on August 1, 2014, in pgp, security. Bookmark the permalink. 2 Comments.

  1. http://serverfault.com/questions/293101/validating-signature-trust-with-gpg suggests using status-fd and gives example, but the whole approach looks horrible

  2. Thanks Simon.

    On the basis of least-bad-solution, I’ve adapted something from that. With the extra proviso that in this case we’re dealing with a third-party signature, so there’s an additional attack vector to worry about where gpg verifies a good and trusted signature not from the nginx devs but from Evil Hacker.

    I now have a separate script to invoke from my Makefile:

    #!/bin/sh

    # gpg alone isn’t good enough: see
    # https://bahumbug.wordpress.com/2014/08/01/scripting-with-gpg/

    # Workaround snarfed from
    # http://serverfault.com/questions/293101/validating-signature-trust-with-gpg
    # in the absence of a better solution

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

    # Automatically verify as much as we can
    gpg –status-file $tmpfile –verify “$@” || exit 1
    egrep -q ‘^\[GNUPG:] TRUST_(ULTIMATE|FULLY)’ $tmpfile || exit 1

    # If it’s signed by “Evil Hacker <evil.hacker@nsa.gov>”
    # give the user a chance to check.

    echo
    echo “======= SECURITY ========”
    echo
    echo “We have just downloaded nginx and verified its PGP signature.”
    echo “Please confirm that you trust the signatory as shown above”
    /bin/echo -n “Signature trusted [Yn]? ==> ”
    read yn
    [ “x$yn” = “xY” ] || [ “x$yn” = “xy” ] || [ “x$yn” = “x” ] || exit 1
    exit 0

Leave a comment