Showing signatures for exported/unimported keys using the Python GPGME bindings

Paul Boddie paul at boddie.org.uk
Fri Aug 23 17:03:11 CEST 2024


On Friday, 23 August 2024 10:11:45 CEST Werner Koch wrote:
> 
> you might have noticed that we don't have a real maintainer for the
> Python bindings anymore.  The last maintainer did a lot on the
> documentation front but less on the actual inner workings.

Thanks for the reply! I didn't notice, unfortunately. I did find a discussion 
from a few years back where two competing sets of bindings were discussed, one 
using SWIG and one being constructed using the Python C API directly:

https://lists.gnupg.org/pipermail/gnupg-devel/2016-May/031156.html

> Instead of having used the convient SWIG based bindings we should have
> done a manual binding to make sure that we have a stable API (and less
> compiler warning ;-).  It is more work of course but counting in all the
> problems and the endless hours of fixing stuff this would have been
> better in the end.

I haven't done library binding work for Python in many years, so I can't 
comment on whether SWIG is the most appropriate tool. I suppose there is 
always the hope that a tool can automate the wrapping of the underlying 
library entirely, even if the result is still fairly low-level. I would have 
to reacquaint myself with the current selection of tools to see if that ever 
became remotely feasible.

Many years ago, I made a high-level library for libxml2 based on the low-level 
Python bindings generated by the tool and resources in that library's own 
repository. So, I recognise that starting with low-level bindings and making 
higher-level bindings in a layered approach is entirely satisfactory. Others 
chose to use Pyrex/Cython to wrap libxml2 and to hide the underlying C 
library, but browsing their code suggests that this is also quite an intensive 
job:

https://github.com/lxml/lxml/tree/master/src/lxml

There may be benefits in using Cython instead of the Python C API directly, 
however.

> > P.S. Some kind of quick reference mapping gpg operations to the API would
> > be rather helpful.

> The original SWIG idea was that there is no need for a separate
> documentation.  The higher level and more pythonese API was added latter
> and is indeed not comprehensive.

I didn't find any documentation for the higher-level bindings as provided, 
although I did find documentation for previous incarnations of the bindings 
online. For example:

https://pygpgme.readthedocs.io/en/latest/

> It might be important for your considerations that we plan to split off
> the language bindings into separate repos and tarballs.  The main driver
> for this is that the Qt folks prefer to use cmake and having both build
> systems (cmake and autotools) is not easy for the maintainers.  The
> Python bindings will thus also be split into a separate library and it
> will allow to have a maintainer who does not need to follow the gpgme
> development all the day but instead rely on the stable GPGME API.
> 
> See https://dev.gnupg.org/T7262

That seems like a reasonable approach, given the strong preferences people 
have for (and against) various build systems, plus the nightmare of having to 
integrate them within a common framework.

However, in the specific case involving the lack of signatures for keys that 
are not resident in a keychain, I see that the behaviour is explained by code 
in the GPGME library itself. Looking at src/keylist.c, there are three 
functions, each calling some underlying function:

gpgme_op_keylist_start           -> _gpgme_engine_op_keylist
gpgme_op_keylist_ext_start       -> _gpgme_engine_op_keylist_ext
gpgme_op_keylist_from_data_start -> _gpgme_engine_op_keylist_data

These are described in the documentation, of course:

https://www.gnupg.org/documentation/manuals/gpgme/Listing-Keys.html

However, I see that the data-related function does not propagate keylist_mode 
from the context to the underlying function. In src/engine.c, the 
_gpgme_engine_op_keylist_data function invokes the appropriate engine 
operation without the mode.

And in src/engine-gpg.c, which is the only engine implementing the 
keylist_data operation, I see that the gpg_keylist_data function does not 
support the mode and therefore cannot introduce --with-sig-list to the command 
options.

In contrast, the other keylist operations employ the gpg_keylist_build_options 
function to convert the mode to appropriate command options, although I see 
that --with-sig-check, not --with-sig-list, is actually introduced if 
GPGME_KEYLIST_MODE_SIGS is specified.

So, I think I am mostly left wondering whether this treatment or lack of 
treatment of the mode was intentional in GPGME for keylist_data, or whether it 
was an oversight that can be remedied.

Paul





More information about the Gnupg-devel mailing list