ssh-add -l shows you all ssh-keys that have been added with
ssh-add ~/.ssh/id_yourkey. How do I do the analogous thing with gpg and gpg-agent, in other words, ask it to show a list of cached keys?
You may not be able to do this, at least not yet, or at least not in the general case. However, I will share what I have learned, and look forward to updating this answer in due course.
First of all, unlike the
ssh-agent capability, which actually caches private keys,
gpg-agent can cache either keys or passphrases. It is up to each client which to cache, and
gpg just uses
gpg-agent to cache the passphrase.
You can interact with
gpg-agent using the
gpg-connect-agent utility. In the example that follows, I am passing commands one at a time via STDIN.
$ CACHEID="ThisIsTheTrickyPart" $ ERRSTR="Error+string+goes+here" $ PMTSTR="Prompt" $ DESSTR="Description+string+goes+here" $ echo "GET_PASSPHRASE --data $CACHEID $ERRSTR $PMTSTR $DESSTR" | gpg-connect-agent D MyPassPhrase OK
gpg-connect-agent and passing in this command, the
pinentry command configured on my system uses the error, prompt, and description strings to prompt for a passphrase. In this case I entered "MyPassPhrase" which is what is returned in the structured output (see image below). If I send
gpg-agent again with the same
$CACHEID, it returns the cached passphrase instead of using
GET_PASSPHRASE also accepts a
--no-ask option which will return an error on a cache miss. Here I use "NotCachedID" as the cache ID, and use dummy strings for the required arguments that
gpg-agent will not use.
$ echo "GET_PASSPHRASE --no-ask NotCachedID Err Pmt Des" | gpg-connect-agent ERR 67108922 No data <GPG Agent>
In principle, then, you could ask the agent for each maybe-cached passphrase in turn, and check for
ERR in the output. The question then becomes, how do I generate the cache ID? As we see in the example above,
gpg-agent is liberal in what it accepts as the cache ID. It turns out that
gpg computes a fingerprint on the public key and uses a hex-coded string representation as the cache ID, but the trouble is that this fingerprint is not the same as the fingerprint you can learn via
gpg --fingerprint --list-secret-keys. This digest is called keygrip (because it is computed over the raw key material only whereas the fingerprint is calculcated over the key material and the creation timestamp). If you really want to continue down this path, you will have to find out how to generate the correct fingerprint for each of the keys you wish to check (this will be easy using the next generation of GnuPG, 2.1, with the option
Warning: The output from
GET_PASSPHRASE actually contains the passphrase in the clear. Even if you leave off the
--data option, the passphrase is plainly visible as a hex-coded string. It is probably a Very Bad Idea(tm) to muck around with this unless you know what you are doing, and take the appropriate precautions.
On later versions of gnupg (tested with 2.1.18) use:
gpg --fingerprint --with-keygrip <email>
to get the keygrip, then
echo "KEYINFO --no-ask <keygrip> Err Pmt Des" | gpg-connect-agent
to see whether it's cached or not.
On later versions of GnuPG (tested with 2.2.9) it is also possible to list the keygrips that are currently cached by the agent using the command
keyinfo --list with
$ gpg-connect-agent 'keyinfo --list' /bye S KEYINFO 866C3DE249CF81E31A3691845DBADE2809487FF5 D - - 1 P - - - S KEYINFO 04278155E72CAE8FF1548FE161F1B8F7673824F4 D - - - P - - - OK
1 in the seventh column indicates that the keygrip is cached.
The association between a keygrip and the key it represents can be retrieved with
gpg --list-secret-keys --with-keygrip.
To get the cacheid you need to mention
--fingerprint twice, for example:
$ gpg --fingerprint --fingerprint firstname.lastname@example.org pub 1024D/517D0F0E 2000-10-10 Key fingerprint = C75D C40A 11D7 AF88 9981 ED5B C86B A06A 517D 0F0E uid Linux Kernel Archives Verification Key <email@example.com> sub 4096g/E50A8F2A 2000-10-10 Key fingerprint = E851 4C25 10C6 0291 0D47 A008 7C8B 4360 E50A 8F2A
The cacheid in this case would be
The cacheid is the full fingerprint of the key.
gpg --fingerprint firstname.lastname@example.org