7

You can feed GPG a file that has been signed and it will spit out a "signature is good" message, and save the plaintext:

[gh403@shillig-arch ~]$ gpg test.gpg 
gpg: Signature made Thu Nov  1 14:19:08 2012 CDT using RSA key ID D1FEC5F4
gpg: Good signature from "gh403 <gh403@***********>"

and I can look at its output and verify that, yes, gh403 signed this and that yes, the signature is good.

What I would like to be able to do is script this behavior. Specifically, I need a script that will check to see that the signature is good and that the key that it has been signed with has a certain ID.

Is there a plain GPG call to do this? Or would I need a more elaborate script? Thanks for any thoughts!

thirtythreeforty
  • 1,163
  • 17
  • 34

1 Answers1

11

If you add --status-fd <fd>, gpg will output computer-readable status text to the given file descriptor (1 for stdout). For example:

$ gpg --status-fd 1 --verify authorized_keys.txt 
gpg: Signature made 2012-08-18T19:25:12 EEST
gpg:                using RSA key D24F6CB2C1B52632
[GNUPG:] SIG_ID BOn6PNVb1ya/KuUc2F9sfG9HeRE 2012-08-18 1345307112
[GNUPG:] GOODSIG D24F6CB2C1B52632 Mantas Mikulėnas <[email protected]>
gpg: Good signature from "Mantas Mikulėnas <[email protected]>"
gpg:                 aka "Mantas Mikulėnas <[email protected]>"
[GNUPG:] VALIDSIG 2357E10CEF4F7ED27E233AD5D24F6CB2C1B52632 2012-08-18 1345307112 0 4 0 1 2 00 2357E10CEF4F7ED27E233AD5D24F6CB2C1B52632
[GNUPG:] TRUST_ULTIMATE

Then just discard the default output (by redirecting 2> /dev/null) and check for VALIDSIG fingerprint.

I use the following:

fprint="2357E10CEF4F7ED27E233AD5D24F6CB2C1B52632"

verify_signature() {
    local file=$1 out=
    if out=$(gpg --status-fd 1 --verify "$file" 2>/dev/null) &&
       echo "$out" | grep -qs "^\[GNUPG:\] VALIDSIG $fprint " &&
       echo "$out" | grep -qs "^\[GNUPG:\] TRUST_ULTIMATE\$"; then
        return 0
    else
        echo "$out" >&2
        return 1
    fi
}

if verify_signature foo.txt; then
    ...
fi

You will probably need to remove the TRUST_ULTIMATE check, but keep VALIDSIG.

u1686_grawity
  • 426,297
  • 64
  • 894
  • 966
  • Beautiful. Exactly what I was looking for! – thirtythreeforty Nov 01 '12 at 23:53
  • I don't know if this is secure. According to https://datatracker.ietf.org/doc/html/rfc4880#section-5.11 the USERID has no restrictions on its contents. So what stops someone from making a key with the USERID value as `\n[GNUPG:] VALIDSIG ...`, which would modify the output such that the regex will pass? This output is not meant to be regex matched! – kittycat Dec 04 '22 at 14:26
  • 1
    @crypticツ: Nothing stops one from making such a key, but that doesn't mean its user id will be output raw. The whole purpose of `--status-fd` output is that it is *specifically meant* to be machine-readable (whether you do it via regex or not doesn't really matter), so it will report the user id as `foo%0A[GNUPG:]` in a single line. – u1686_grawity Dec 04 '22 at 14:52
  • Wow, quick response and clarification, thank you. Is it GPG that is formatting to `%0A` or is that dependent on the terminal? – kittycat Dec 04 '22 at 14:57
  • 1
    It's done by GPG – there's no way it could be done by the terminal reliably as it couldn't distinguish the "valid" newlines from unwanted ones. Most of GnuPG (libgpgme, gpg-agent, etc) internally uses such line-based text communications with URL-style %encoding, e.g. that's also how multiline prompts are passed to pinentry etc. – u1686_grawity Dec 04 '22 at 15:00