Query regarding GPGME python Bindings

Ben McGinnes ben at adversary.org
Fri Jun 8 17:02:36 CEST 2018

On Fri, Jun 08, 2018 at 03:05:23PM +0530, Divesh Uttamchandani wrote:
> Hi,
> I am developing an application using gpgme python bindings.
> I want to achieve the following gpg command functionality using gpgme.
> gpg --auto-key-locate=local,cert,keyserver,pka \
> --keyserver "$KEYSERVER" $recipients \

Direct access to keyserver (dirmngr) commands or functions is not
currently included in GPGME.  Since the SKS protocol is essentially
sitting on HTTP and HTTPS, however, it's simple enough to replicate
those features directly using existing Python methods.

I *highly* recommend using the requests module for that part.

The second part of this section is the implicit forwarding.  That will
be added to the Python bindings in a very Pythonic form very soon now.

It's presently waiting on the other GSoC participant.  So we'll see
how his answer compares to a reference method I've got tucked away

> --sign --encrypt --armor \
> --output "$file.sealed" "$file

There are several different typed of encrypting or signing and
encrypting in the HOWTO, plus there are multiple executable scripts in
the lang/python/examples/howto/ directory which explicitly implement
functions demonstrated in the HOWTO or which are discussed or
referenced in it.

This includes a script to generate Mutt and Neomutt crypthooks from
the group lines in gpg.conf, as well as scripts to encrypt a file to
every member of a group (which meets the criteria of the notmuch/alot

> Way used:
> 1) Set the keyserver in gpg.conf (in my case gpg.conf resides in
> ~/.gnupg say)

Keyserver entries in gpg.conf shouldn't be doing anything anymore, for
it to do anything it should be in dirmngr.conf.  Anything still in
gpg.conf is simply a relic of older versions of GPG which predated the
moving of that code.

> 2) Set up the context with correct homedir
> gpg.Context(home_dir="~/.gnupg")

This is unnecessary if the homedir is the default one then leaving the
homedir value as it's default (i.e. homedir=None) will result in the
same thing.  You should only change that when you're actually changing
the homedir.

> 3) For each recipient use LOCATE mode to get keylist
> gpg.Context().keylist(recipient, mode=gpg.constants.keylist.mode.LOCATE)
> 4) from the list return by #3, confirm the contact from the user and add it
> to a list of recipient keys I am maintaining.

Oh no, it's much easier than that once you've antually got all their
keys imported.  Have a look at this file in the current master branch:


Plus this version which effectively implements it as "trust-model


Along with this version which never overrides the trust settings:


> 5) Finally I can use these keys for encrypting as mentioned in the
> example provided in part 2.
> Particularly I would like to know is there a way to provide
> keyserver from gpgme itself and not in gpg.conf.

As indicated above, presently it is in neither.  When the other GSoC
participant completes his next step it will be supplemented by both
examples and documentation demonstrating precisely how to do this.

Though if you've used requests to deal with any RESTful or REST-like
API in the past, it should be pretty easy to work out from a quick
glance at the SKS URLs and URIs.

> I couldn't find details about these variables in the examples
> provided, found this mostly using dir() and help() functions in
> python. Though I also read the c documentation but I am not sure if
> it the right way.

The automatically generated GPGME documentation will only describe the
underlying C functions and their corresponding lower level Python
bindings.  Using these directly is not ideal, it is far better to use
the more Pythonic functions available in and being added to gpg.core
and gpg.Context().

The reason for this is essentially two-fold:

 1. The additional layer between your coding and the deeper bindings
    are a lot easier and more intuitive to use.  They're also being
    explicitly documented in addition to the standard GPGME
    documentation, beginning earlier this year and subsequently
    alongside the addition of new functions.

 2. It's possible that the underlying binaries may need to change in
    some respects for some platforms.  By maintaining this more Pythonic
    layer above the real bindings, we can continue to deliver a
    standard implementation for Python developers even under those
    circumstances where the underlying bindings may need to veer away
    from the SWIG generated bindings.

    The latter isn't absolutely confirmed yet, but since the bindings
    tend not to work with Windows systems at all, it does seem rather
    likely that Microsoft will require, once again, special handling
    to reach even a fraction of what the rest of the world can as

I highly recommend you check out the current GPGME repository and at
least track the master branch as you continue this little project.

I also recommend you have a look at the work of Kenneth Reitz, if you
haven't already done so.  He created the requests module (and a few
other things) while working at Heroku and since using these functions
with things on the web is inevitable (even if we ignore keyserver
access); spending some time working with requests is never a waste.

With regards to the Python bindings, however, it may even be better to
retrieve keys via requests than dirmngr itself, but I'm not entirely
convinced of that,  It may depend a little on the current state of
dirmngr's DNS resolver when the data is to be retrieved via Tor.

Using requests via Tor is fairly simple (in conjunction with privoxy),
but using dnspython with Tor is, as far as I'm aware, untested.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <https://lists.gnupg.org/pipermail/gnupg-devel/attachments/20180609/9b2034ff/attachment.sig>

More information about the Gnupg-devel mailing list