How to prevent passphrase-caching from within a gpgme-based Python script?
angel at pgp.16bits.net
Tue Apr 16 23:23:52 CEST 2019
On 2019-04-12 at 07:12 -0400, Kynn Jones wrote:
> Hi everyone!
> The following short Python script takes three command-line arguments:
> a passphrase, an input path, and an output path. Then it uses the
> passphrase to decrypt the contents of the input path, and puts the
> decrypted content in the output path.
> This decryption works fine, as long as the correct passphrase is
> provided, but it apparently results in the caching of such correct
> passphrase, so that any subsequent decryption attempts succeed
> irrespective of the passphrase one provides. (I give a fuller
> illustration of what I mean at the end of this post, together with
> version details.)
> Clearly, there's some passphrase caching going on, but I don't really
> understand the details.
Yes. gpg will use a gpg-agent, launching it if needed, and that agent is
caching the passphrase:
> --default-cache-ttl n
> Set the time a cache entry is valid to n seconds. The default is 600 seconds.
> --max-cache-ttl n
> Set the maximum time a cache entry is valid to n seconds. After this time a cache entry
> will be expired even if it has been accessed recently or has been set using gpg-preset-
> passphrase. The default is 2 hours (7200 seconds).
> What I want to know is: how can I modify the Python script so that it
> disables the caching of passphrases? Note that I am not interested in
> how to disable passphrase caching outside of the script! I want the
> script to disable passphrase caching autonomously. Is that possible?
There doesn't seem to be any command to set a passphrase with just a ttl
in the agent protocol. Which is not that strange, given the gpg client
passing the passphrase to the agent is the weird case. It could of
course issue a CLEAR_PASSPHRASE before each operation, but that would be
I think you should launch your own gpg-agent for your script, with the
configuration you wish. For example, I expect that running this wrapper
instead of demo.py would fix it:
eval $(gpg-agent --daemon --sh --max-cache-ttl 0)
exec python ./demo.py "$@"
Of course, you could instead run gpg-agent from python and set
GPG_AGENT_INFO there. The gpg python package is calling gpg under the
hood, so it should pick the GPG_AGENT_INFO variable from the
In the script above, after running the script you could do
> kill $(echo "$GPG_AGENT_INFO" | cut -d : -f 2)
since nobody would use that agent again, anyway.
A more optimized version would use a dedicated agent just for demo.py,
but reuse it amongst several invocations of demo.py.
More information about the Gnupg-users