How do I verify a gpg signature matches a public key file?

Rich picture Rich · Sep 25, 2013 · Viewed 62.2k times · Source

I know how to use gpg verify like this:

$ gpg --verify somefile.sig
gpg: Signature made Tue 23 Jul 2013 13:20:02 BST using RSA key ID E1B768A0
gpg: Good signature from "Richard W.M. Jones <[email protected]>"
gpg:                 aka "Richard W.M. Jones <[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: F777 4FB1 AD07 4A7E 8C87  67EA 9173 8F73 E1B7 68A0

But what I really want to do is to verify the file against a specific public key file.

The motivation is as part of a program that downloads large files from a website and needs to verify they haven't been tampered with before it uses them. The website will contain the files and the signatures. The program will ship with the GPG public key. When I upload the files to the website I will sign them with the corresponding private key (not distributed obviously). It seems like the program should be able to do something like:

gpg --no-default-keyring --verify file.sig \
    --is-signed-with /usr/share/program/goodkey.asc

But gpg has no option like this. It looks like the only way to do it would be to parse the printed output of the gpg command which seems very unsafe (it contains text controlled by the attacker).

Edit: I don't know what the etiquette is around here for answering ones own questions, but the answer I found was to use the --status-fd flag. This flag generates nicely parsable output which I can check for the desired fingerprint:

gpg --status-fd <N> --verify file.sig

produces on fd N:

[GNUPG:] SIG_ID rpG8ATxU8yZr9SHL+VC/WQbV9ac 2013-07-23 1374582002
[GNUPG:] GOODSIG 91738F73E1B768A0 Richard W.M. Jones <[email protected]>
[GNUPG:] VALIDSIG F7774FB1AD074A7E8C8767EA91738F73E1B768A0 2013-07-23 1374582002 0 4 0 1 2 00 F7774FB1AD074A7E8C8767EA91738F73E1B768A0
[GNUPG:] TRUST_UNDEFINED

This is how, for example, perl's GnuPG library works.

Answer

Ben picture Ben · Sep 26, 2013

The only way to use a specific public key file like a keyring is if the file is in the GPG (OpenPGP) file format and not an ASCII armoured version (e.g. pubkey.gpg not pubkey.asc).

So this will verify the file:

gpg --no-default-keyring --keyring /path/to/pubkey.gpg --verify /path/to/file.txt.gpg

And this will not:

gpg --no-default-keyring --keyring /path/to/pubkey.asc --verify /path/to/file.txt.gpg

EDIT: I've gone into a little more detail on this for a similar question on the SuperUser site:

https://superuser.com/questions/639853/gpg-verifying-signatures-without-creating-trust-chain/650359#650359