Mailing List Archive

Query regarding GPGME python Bindings
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 \
--sign --encrypt --armor \
--output "$file.sealed" "$file

For achieving this i have broken it down to two parts
1. getting the recipients' key locally/keyserver
2. using these keys to encrypt (and sign the data)

I have idea to achieve the functionality of the second part.
I am doubtful about the first, Though I have tried it in following way, I
want to know if I am correct and if there is a better way?

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

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

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.

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.

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.

Regards,
Divesh Uttamchandani
GitHub <https://github.com/diveshuttam> | Linkedin
<https://www.linkedin.com/in/diveshuttam/> | University Profile
<http://www.bits-pilani.ac.in/spp/f2016045>
Re: Query regarding GPGME python Bindings [ In reply to ]
On Fri, Jun 8, 2018 at 11:35 AM, Divesh Uttamchandani <
diveshuttamchandani@gmail.com> wrote:
>
> Way used:
> 1) Set the keyserver in gpg.conf (in my case gpg.conf resides in ~/.gnupg
> say)
>

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

If you can load some settings from a configuration file ('gpg.conf' in this
case),
there should be some way to customize or override those settings. This is
how it usually works. Maybe you should check more carefully the structure
of the object 'gpg'.

Sorry that I can't be more specific or more helpful about this.

Dashamir
Re: Query regarding GPGME python Bindings [ In reply to ]
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
already.

> --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
users.

> 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:

lang/python/examples/howto/encrypt-to-group.py

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

lang/python/examples/howto/encrypt-to-group-gullible.py

Along with this version which never overrides the trust settings:

lang/python/examples/howto/encrypt-to-group-trustno1.py

> 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
standard.

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.


Regards,
Ben
Re: Query regarding GPGME python Bindings [ In reply to ]
On Fri, Jun 8, 2018 at 5:02 PM, Ben McGinnes <ben@adversary.org> wrote:

> 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.
>

As a workaround, or temporary solution, you can also try to use the
commands:
gpg --keyserver="$keyserver" --search-keys "$recipient"
gpg --keyserver="$keyserver" --recv-keys <key_id> <key_id>...
for fetching the recipients that are not available locally.
Later you can replace this with Python code.

Regards,
Dashamir
Re: Query regarding GPGME python Bindings [ In reply to ]
On 2018-06-09 at 01:02 +1000, Ben McGinnes wrote:
> 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.

nit, with pointers to correct terms to hopefully be helpful for those
trying to research and not just be nit-picking: the protocol is HKP (or
HKPS), implemented by a variety of keyservers.

SKS is a protocol for set reconciliation between keyservers and not
implemented (nor appropriate to implement) by GnuPG; it's used by the
SKS software base and one or two other products. The SKS software, like
almost all non-LDAP keyservers, implements an HKP interface too.

I've some more details up at:
<https://people.spodhuis.org/phil.pennock/pgp-keyservers>
including links to the HKP specs, such as they are (a thesis paper and
an expired draft).

-Phil

_______________________________________________
Gnupg-devel mailing list
Gnupg-devel@gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-devel
Re: Query regarding GPGME python Bindings [ In reply to ]
> As a workaround, or temporary solution, you can also try to use the
> commands:
> gpg --keyserver="$keyserver" --search-keys "$recipient"
> gpg --keyserver="$keyserver" --recv-keys <key_id> <key_id>...
> for fetching the recipients that are not available locally.
> Later you can replace this with Python code.
>
> Regards,
> Dashamir

If someone needs code for hkp/hkps, their is some on my own project.

https://github.com/Selfnet/multivault/tree/master/multivault/hkp

It was originally written for urllib2 but I ported it to the requests
library.

https://github.com/dgladkov/python-hkp

Is the original codebase of my code, I modified it in purpose of the
requests library.

---------------------------------------------------------------------


Other question.

Is it possible with gpgme, to create a new initialized homedir.
I only find that option in the gpg cli but not in the gpgme bindings.
How would I achieve that?

Best Regards

Marcel Fest
Re: Query regarding GPGME python Bindings [ In reply to ]
On Sat, Jun 09, 2018 at 09:13:23AM +0200, Marcel Fest wrote:
>
> Is it possible with gpgme, to create a new initialized homedir. I
> only find that option in the gpg cli but not in the gpgme bindings.
> How would I achieve that?

It's possible to specify an alternative homedir in GPGME and thus also
in the Python bindings, just as can currently be done with the GPG
binary.

Creating and populating the entire hidden directory structure,
however, is another matter … which is why I scripted the part of that
which GPGME doesn't do too. That script is here:

lang/python/examples/howto/temp-homedir-config.py

One of the many side benefitswhich grew out of needing to create keys
for the Greatest Secret Agent in the World.


Regards,
Ben
AW: Re: Query regarding GPGME python Bindings [ In reply to ]
Thanks, so i can fully migrate to gpgme Python bindings.

cu

Marcel Fest

---- Ben McGinnes schrieb ----

>On Sat, Jun 09, 2018 at 09:13:23AM +0200, Marcel Fest wrote:
>>
>> Is it possible with gpgme, to create a new initialized homedir. I
>> only find that option in the gpg cli but not in the gpgme bindings.
>> How would I achieve that?
>
>It's possible to specify an alternative homedir in GPGME and thus also
>in the Python bindings, just as can currently be done with the GPG
>binary.
>
>Creating and populating the entire hidden directory structure,
>however, is another matter … which is why I scripted the part of that
>which GPGME doesn't do too. That script is here:
>
>lang/python/examples/howto/temp-homedir-config.py
>
>One of the many side benefitswhich grew out of needing to create keys
>for the Greatest Secret Agent in the World.
>
>
>Regards,
>Ben
>
>_______________________________________________
>Gnupg-devel mailing list
>Gnupg-devel@gnupg.org
>http://lists.gnupg.org/mailman/listinfo/gnupg-devel
Re: Query regarding GPGME python Bindings [ In reply to ]
On Sun, Jun 17, 2018 at 04:21:14PM +0200, Marcel Fest wrote:
> Thanks, so i can fully migrate to gpgme Python bindings.

Awesome. Let me know if you encounter any weirdness along the way.


Regards,
Ben