You can get a parseable list of secret keys in GnuPG by doing:
gpg2 --list-secret-keys --with-colons
The format of the output is described here: http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob_plain;f=doc/DETAILS
I want to write a bash function that tells me if I have both valid encryption and signing keys. Based on the above URL, this is what I came up with:
has_valid_secret_keys() {
return "$(gpg2 --list-secret-keys --with-colons 2>/dev/null | \
awk -F: 'BEGIN { sign = 0; encrypt = 0; }
($1 ~ "sec|ssb") && ($2 ~ "[mfu]") {
if ($12 ~ "s") sign++
if ($12 ~ "e") encrypt++
}
END { print !(sign * encrypt) }')"
}
That is, the Awk script matches secret keys and secret subkeys (field 1) with marginal, full or ultimate validity (field 2), then it maintains a counter of signing and encryption keys based on the matched records' capabilities (field 12). If both these counters are zero, then we have no signing or encryption keys, otherwise we have what we want.
This works great in GnuPG 2.1, but when I try it in GnuPG 2.0, the capability field doesn't appear to be set in the output of --list-secret-keys. It was quite hard work finding the documentation for the output; I presume it must have changed between v2 and v2.1.
Is there a GnuPG-version agnostic (including even GnuPG 1.4, if possible) way of doing this?
EDIT Thanks to Jens Erat's answer, my updated (i.e., working!) bash function is as follows:
has_valid_secret_keys() {
# Check that both valid signing and encryption (sub)keys exist
# Format described at http://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob_plain;f=doc/DETAILS
# First we find the Key IDs of secret keys and subkeys, then we
# reference these against the public keys to check their capabilities
return "$(gpg --list-secret-keys --with-colons 2>/dev/null | \
awk -F: '($1 ~ "sec|ssb") { print $5 }' | \
xargs gpg --list-keys --with-colons 2>/dev/null | \
awk -F: 'BEGIN { sign = 0; encrypt = 0; }
($1 ~ "[ps]ub") && ($2 ~ "[mfu]") {
if ($12 ~ "s") sign++
if ($12 ~ "e") encrypt++
}
END { print !(sign * encrypt) }')"
}