How to check openpgp (gpg) signature against a set of public key blocks

gpg

I have some content that needs to be checked against a predetermined whitelist of OpenPGP (also keyword: gpg) public keys for a valid signature by one of them.

The whitelist is maintained separately. Ideally it would be a concatenation of ascii-armored public key blocks, but a directory with one public key per file would be fine. Because the whitelist is maintained separately, we don't want to use any of gpg's keyring management functionality. If the content is signed by a key in our set of keys, it passes. No different trust levels, no web of trust, etc.

Ideally we would have a program with an interface like this:

some-program KEYS_FILE CONTENT SIGFILE

or, with example arguments,

some-program /etc/ourapp/ourapps_trusted_pubkeys.asc /var/lib/ourapp/newcontent.tar.gz /var/lib/ourapp/newcontent.tar.gz.asc

The quickest way to do this with gpg seems to be:

  • use a temporary file as its keyring
  • point gpg to this using –keyring, but also give –no-default-keyring
  • iterate through the keys in ourapps_trusted_pubkeys.asc, importing them one at a time
  • iterate through the keys again, setting them to trusted with gpg –import-ownertrust
  • run the gpg –verify

This is a huge amount of effort for what I imagine to be a common use case. What am I missing? Does a tool similar to the postulated some-program(1) exist?

Best Answer

The program gpgv / gpgv2 is used for simple checking of signatures. The problem is that exported key files are not recognized as keyring. Thus you have to create a keyring in the first step:

cd /some/tmp/dir || exit 1
test -f pubring.gpg && { rm -f pubring.gpg || exit 1; }
gpg --no-options --no-default-keyring --keyring ./pubring.gpg \
  --secret-keyring ./secring.gpg --import /etc/ourapp/ourapps_trusted_pubkeys.asc

Now /some/tmp/dir/pubring.gpg is a keyring file gpgv can use:

gpgv --keyring /some/tmp/dir/pubring.gpg \
  /var/lib/ourapp/newcontent.tar.gz.asc /var/lib/ourapp/newcontent.tar.gz

If the data file path is the signature path without .asc (like in your example) then you can leave it out.

Related Question