docs: whitespace culled
[gpgme.git] / lang / python / docs / gpgme-python-howto.org
1 #+TITLE: GNU Privacy Guard (GnuPG) Made Easy Python Bindings HOWTO (English)
2 #+AUTHOR: Ben McGinnes
3 #+LATEX_COMPILER: xelatex
4 #+LATEX_CLASS: article
5 #+LATEX_CLASS_OPTIONS: [12pt]
6 #+LATEX_HEADER: \usepackage{xltxtra}
7 #+LATEX_HEADER: \usepackage[margin=1in]{geometry}
8 #+LATEX_HEADER: \setmainfont[Ligatures={Common}]{Times New Roman}
9 #+LATEX_HEADER: \author{Ben McGinnes <ben@gnupg.org>}
10 #+HTML_HEAD_EXTRA: <link type="application/rss+xml" href="https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gpgme.git;a=rss;f=lang/python/docs/GPGMEpythonHOWTOen.org"/>
11
12
13 * Introduction
14   :PROPERTIES:
15   :CUSTOM_ID: intro
16   :END:
17
18 | Version:        | 0.1.4                                    |
19 | GPGME Version:  | 1.12.0-draft                             |
20 | Author:         | [[https://gnupg.org/people/index.html#sec-1-5][Ben McGinnes]] <ben@gnupg.org>             |
21 | Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
22 | Language:       | Australian English, British English      |
23 | xml:lang:       | en-AU, en-GB, en                         |
24
25 This document provides basic instruction in how to use the GPGME
26 Python bindings to programmatically leverage the GPGME library.
27
28
29 ** Python 2 versus Python 3
30    :PROPERTIES:
31    :CUSTOM_ID: py2-vs-py3
32    :END:
33
34 Though the GPGME Python bindings themselves provide support for both
35 Python 2 and 3, the focus is unequivocally on Python 3 and
36 specifically from Python 3.4 and above.  As a consequence all the
37 examples and instructions in this guide use Python 3 code.
38
39 Much of it will work with Python 2, but much of it also deals with
40 Python 3 byte literals, particularly when reading and writing data.
41 Developers concentrating on Python 2.7, and possibly even 2.6, will
42 need to make the appropriate modifications to support the older string
43 and unicode types as opposed to bytes.
44
45 There are multiple reasons for concentrating on Python 3; some of
46 which relate to the immediate integration of these bindings, some of
47 which relate to longer term plans for both GPGME and the python
48 bindings and some of which relate to the impending EOL period for
49 Python 2.7.  Essentially, though, there is little value in tying the
50 bindings to a version of the language which is a dead end and the
51 advantages offered by Python 3 over Python 2 make handling the data
52 types with which GPGME deals considerably easier.
53
54
55 ** Examples
56    :PROPERTIES:
57    :CUSTOM_ID: howto-python3-examples
58    :END:
59
60 All of the examples found in this document can be found as Python 3
61 scripts in the =lang/python/examples/howto= directory.
62
63
64 * GPGME Concepts
65   :PROPERTIES:
66   :CUSTOM_ID: gpgme-concepts
67   :END:
68
69
70 ** A C API
71    :PROPERTIES:
72    :CUSTOM_ID: gpgme-c-api
73    :END:
74
75 Unlike many modern APIs with which programmers will be more familiar
76 with these days, the GPGME API is a C API.  The API is intended for
77 use by C coders who would be able to access its features by including
78 the =gpgme.h= header file with their own C source code and then access
79 its functions just as they would any other C headers.
80
81 This is a very effective method of gaining complete access to the API
82 and in the most efficient manner possible.  It does, however, have the
83 drawback that it cannot be directly used by other languages without
84 some means of providing an interface to those languages.  This is
85 where the need for bindings in various languages stems.
86
87
88 ** Python bindings
89    :PROPERTIES:
90    :CUSTOM_ID: gpgme-python-bindings
91    :END:
92
93 The Python bindings for GPGME provide a higher level means of
94 accessing the complete feature set of GPGME itself.  It also provides
95 a more pythonic means of calling these API functions.
96
97 The bindings are generated dynamically with SWIG and the copy of
98 =gpgme.h= generated when GPGME is compiled.
99
100 This means that a version of the Python bindings is fundamentally tied
101 to the exact same version of GPGME used to generate that copy of
102 =gpgme.h=.
103
104
105 ** Difference between the Python bindings and other GnuPG Python packages
106    :PROPERTIES:
107    :CUSTOM_ID: gpgme-python-bindings-diffs
108    :END:
109
110 There have been numerous attempts to add GnuPG support to Python over
111 the years.  Some of the most well known are listed here, along with
112 what differentiates them.
113
114
115 *** The python-gnupg package maintained by Vinay Sajip
116     :PROPERTIES:
117     :CUSTOM_ID: diffs-python-gnupg
118     :END:
119
120 This is arguably the most popular means of integrating GPG with
121 Python.  The package utilises the =subprocess= module to implement
122 wrappers for the =gpg= and =gpg2= executables normally invoked on the
123 command line (=gpg.exe= and =gpg2.exe= on Windows).
124
125 The popularity of this package stemmed from its ease of use and
126 capability in providing the most commonly required features.
127
128 Unfortunately it has been beset by a number of security issues in the
129 past; most of which stemmed from using unsafe methods of accessing the
130 command line via the =subprocess= calls.  While some effort has been
131 made over the last two to three years (as of 2018) to mitigate this,
132 particularly by no longer providing shell access through those
133 subprocess calls, the wrapper is still somewhat limited in the scope
134 of its GnuPG features coverage.
135
136 The python-gnupg package is available under the MIT license.
137
138
139 *** The gnupg package created and maintained by Isis Lovecruft
140     :PROPERTIES:
141     :CUSTOM_ID: diffs-isis-gnupg
142     :END:
143
144 In 2015 Isis Lovecruft from the Tor Project forked and then
145 re-implemented the python-gnupg package as just gnupg.  This new
146 package also relied on subprocess to call the =gpg= or =gpg2=
147 binaries, but did so somewhat more securely.
148
149 The naming and version numbering selected for this package, however,
150 resulted in conflicts with the original python-gnupg and since its
151 functions were called in a different manner to python-gnupg, the
152 release of this package also resulted in a great deal of consternation
153 when people installed what they thought was an upgrade that
154 subsequently broke the code relying on it.
155
156 The gnupg package is available under the GNU General Public License
157 version 3.0 (or any later version).
158
159
160 *** The PyME package maintained by Martin Albrecht
161     :PROPERTIES:
162     :CUSTOM_ID: diffs-pyme
163     :END:
164
165 This package is the origin of these bindings, though they are somewhat
166 different now.  For details of when and how the PyME package was
167 folded back into GPGME itself see the /Short History/ document[fn:1]
168 in the Python bindings =docs= directory.[fn:2]
169
170 The PyME package was first released in 2002 and was also the first
171 attempt to implement a low level binding to GPGME.  In doing so it
172 provided access to considerably more functionality than either the
173 =python-gnupg= or =gnupg= packages.
174
175 The PyME package is only available for Python 2.6 and 2.7.
176
177 Porting the PyME package to Python 3.4 in 2015 is what resulted in it
178 being folded into the GPGME project and the current bindings are the
179 end result of that effort.
180
181 The PyME package is available under the same dual licensing as GPGME
182 itself: the GNU General Public License version 2.0 (or any later
183 version) and the GNU Lesser General Public License version 2.1 (or any
184 later version).
185
186
187 * GPGME Python bindings installation
188   :PROPERTIES:
189   :CUSTOM_ID: gpgme-python-install
190   :END:
191
192
193 ** No PyPI
194    :PROPERTIES:
195    :CUSTOM_ID: do-not-use-pypi
196    :END:
197
198 Most third-party Python packages and modules are available and
199 distributed through the Python Package Installer, known as PyPI.
200
201 Due to the nature of what these bindings are and how they work, it is
202 infeasible to install the GPGME Python bindings in the same way.
203
204 This is because the bindings use SWIG to dynamically generate C
205 bindings against =gpgme.h= and =gpgme.h= is generated from
206 =gpgme.h.in= at compile time when GPGME is built from source.  Thus to
207 include a package in PyPI which actually built correctly would require
208 either statically built libraries for every architecture bundled with
209 it or a full implementation of C for each architecture.
210
211 See the additional notes regarding [[#snafu-cffi][CFFI and SWIG]] at the end of this
212 section for further details.
213
214
215 ** Requirements
216    :PROPERTIES:
217    :CUSTOM_ID: gpgme-python-requirements
218    :END:
219
220 The GPGME Python bindings only have three requirements:
221
222 1. A suitable version of Python 2 or Python 3.  With Python 2 that
223    means Python 2.7 and with Python 3 that means Python 3.4 or higher.
224 2. [[https://www.swig.org][SWIG]].
225 3. GPGME itself.  Which also means that all of GPGME's dependencies
226    must be installed too.
227
228
229 ** Installation
230    :PROPERTIES:
231    :CUSTOM_ID: installation
232    :END:
233
234 Installing the Python bindings is effectively achieved by compiling
235 and installing GPGME itself.
236
237 Once SWIG is installed with Python and all the dependencies for GPGME
238 are installed you only need to confirm that the version(s) of Python
239 you want the bindings installed for are in your =$PATH=.
240
241 By default GPGME will attempt to install the bindings for the most
242 recent or highest version number of Python 2 and Python 3 it detects
243 in =$PATH=.  It specifically checks for the =python= and =python3=
244 executables first and then checks for specific version numbers.
245
246 For Python 2 it checks for these executables in this order: =python=,
247 =python2= and =python2.7=.
248
249 For Python 3 it checks for these executables in this order: =python3=,
250 =python3.6=, =python3.5=, =python3.4= and =python3.7=.[fn:3]
251
252
253 *** Installing GPGME
254     :PROPERTIES:
255     :CUSTOM_ID: install-gpgme
256     :END:
257
258 See the GPGME =README= file for details of how to install GPGME from
259 source.
260
261
262 ** Known Issues
263    :PROPERTIES:
264    :CUSTOM_ID: snafu
265    :END:
266
267 There are a few known issues with the current build process and the
268 Python bindings.  For the most part these are easily addressed should
269 they be encountered.
270
271
272 *** Breaking Builds
273     :PROPERTIES:
274     :CUSTOM_ID: snafu-a-swig-of-this-builds-character
275     :END:
276
277 Occasionally when installing GPGME with the Python bindings included
278 it may be observed that the =make= portion of that process induces a
279 large very number of warnings and, eventually errors which end that
280 part of the build process.  Yet following that with =make check= and
281 =make install= appears to work seamlessly.
282
283 The cause of this is related to the way SWIG needs to be called to
284 dynamically generate the C bindings for GPGME in the first place.  So
285 the entire process will always produce =lang/python/python2-gpg/= and
286 =lang/python/python3-gpg/= directories.  These should contain the
287 build output generated during compilation, including the complete
288 bindings and module installed into =site-packages=.
289
290 Occasionally the errors in the early part or some other conflict
291 (e.g. not installing as */root/* or */su/*) may result in nothing
292 being installed to the relevant =site-packages= directory and the
293 build directory missing a lot of expected files.  Even when this
294 occurs, the solution is actually quite simple and will always work.
295
296 That solution is simply to run the following commands as either the
297 *root* user or prepended with =sudo -H=[fn:4] in the =lang/python/=
298 directory:
299
300 #+BEGIN_SRC shell
301   /path/to/pythonX.Y setup.py build
302   /path/to/pythonX.Y setup.py build
303   /path/to/pythonX.Y setup.py install
304 #+END_SRC
305
306 Yes, the build command does need to be run twice.  Yes, you still need
307 to run the potentially failing or incomplete steps during the
308 =configure=, =make= and =make install= steps with installing GPGME.
309 This is because those steps generate a lot of essential files needed,
310 both by and in order to create, the bindings (including both the
311 =setup.py= and =gpgme.h= files).
312
313
314 **** IMPORTANT Note
315      :PROPERTIES:
316      :CUSTOM_ID: snafu-swig-build-note
317      :END:
318
319 If specifying a selected number of languages to create bindings for,
320 try to leave Python last.  Currently the majority of the other
321 language bindings are also preceding Python of either version when
322 listed alphabetically and so that just happens by default currently.
323
324 If Python is set to precede one of the other languages then it is
325 possible that the errors described here may interrupt the build
326 process before generating bindings for those other languages.  In
327 these cases it may be preferable to configure all preferred language
328 bindings separately with alternative =configure= steps for GPGME using
329 the =--enable-languages=$LANGUAGE= option.
330
331
332 *** Multiple installations
333     :PROPERTIES:
334     :CUSTOM_ID: snafu-the-full-monty
335     :END:
336
337 For a veriety of reasons it may be either necessary or just preferable
338 to install the bindings to alternative installed Python versions which
339 meet the requirements of these bindings.
340
341 On POSIX systems this will generally be most simply achieved by
342 running the manual installation commands (build, build, install) as
343 described in the previous section for each Python installation the
344 bindings need to be installed to.
345
346 As per the SWIG documentation: the compilers, libraries and runtime
347 used to build GPGME and the Python Bindings *must* match those used to
348 compile Python itself, including the version number(s) (at least going
349 by major version numbers and probably minor numbers too).
350
351 On most POSIX systems, including OS X, this will very likely be the
352 case in most, if not all, cases.
353
354
355 *** Won't Work With Windows
356     :PROPERTIES:
357     :CUSTOM_ID: snafu-runtime-not-funtime
358     :END:
359
360 There are semi-regular reports of Windows users having considerable
361 difficulty in installing and using the Python bindings at all.  Very
362 often, possibly even always, these reports come from Cygwin users
363 and/or MinGW users and/or Msys2 users.  Though not all of them have
364 been confirmed, it appears that these reports have also come from
365 people who installed Python using the Windows installer files from the
366 [[https://python.org][Python website]] (i.e. mostly MSI installers, sometimes self-extracting
367 =.exe= files).
368
369 The Windows versions of Python are not built using Cygwin, MinGW or
370 Msys2; they're built using Microsoft Visual Studio.  Furthermore the
371 version used is /considerably/ more advanced than the version which
372 MinGW obtained a small number of files from many years ago in order to
373 be able to compile anything at all.  Not only that, but there are
374 changes to the version of Visual Studio between some micro releases,
375 though that is is particularly the case with Python 2.7, since it has
376 been kept around far longer than it should have been.
377
378 There are two theoretical solutions to this issue:
379
380  1. Compile and install the GnuPG stack, including GPGME and the
381     Python bibdings using the same version of Microsoft Visual Studio
382     used by the Python Foundation to compile the version of Python
383     installed.
384
385     If there are multiple versions of Python then this will need to be
386     done with each different version of Visual Studio used.
387
388  2. Compile and install Python using the same tools used by choice,
389     such as MinGW or Msys2.
390
391 Do *not* use the official Windows installer for Python unless
392 following the first method.
393
394 In this type of situation it may even be for the best to accept that
395 there are less limitations on permissive software than free software
396 and simply opt to use a recent version of the Community Edition of
397 Microsoft Visual Studio to compile and build all of it, no matter
398 what.
399
400 Investigations into the extent or the limitations of this issue are
401 ongoing.
402
403
404 *** CFFI is the Best™ and GPGME should use it instead of SWIG
405     :PROPERTIES:
406     :CUSTOM_ID: snafu-cffi
407     :END:
408
409 There are many reasons for favouring [[https://cffi.readthedocs.io/en/latest/overview.html][CFFI]] and proponents of it are
410 quite happy to repeat these things as if all it would take to switch
411 from SWIG to CFFI is repeating that list as if it were a new concept.
412
413 The fact is that there are things which Python's CFFI implementation
414 cannot handle in the GPGME C code.  Beyond that there are features of
415 SWIG which are simply not available with CFFI at all.  SWIG generates
416 the bindings to Python using the =gpgme.h= file, but that file is not
417 a single version shipped with each release, it too is generated when
418 GPGME is compiled.
419
420 CFFI is currently unable to adapt to such a potentially mutable
421 codebase.  If there were some means of applying SWIG's dynamic code
422 generation to produce the Python/CFFI API modes of accessing the GPGME
423 libraries (or the source source code directly), but such a thing does
424 not exist yet either and it currently appears that work is needed in
425 at least one of CFFI's dependencies before any of this can be
426 addressed.
427
428 So if you're a massive fan of CFFI; that's great, but if you want this
429 project to switch to CFFI then rather than just insisting that it
430 should, I'd suggest you volunteer to bring CFFI up to the level this
431 project needs.
432
433 If you're actually seriously considering doing so, then I'd suggest
434 taking the =gpgme-tool.c= file in the GPGME =src/= directory and
435 getting that to work with any of the CFFI API methods (not the ABI
436 methods, they'll work with pretty much anything).  When you start
437 running into trouble with "ifdefs" then you'll know what sort of
438 things are lacking.  That doesn't even take into account the amount of
439 work saved via SWIG's code generation techniques either.
440
441 There's a greater likelihood of turning to Cython to add something to
442 these bindings at this point than there is of turning to CFFI.  Except
443 that there's little reason to do so when the C code in question either
444 already exists or could be produced fairly quickly by the far more
445 expedient means of asking either [[https://gnupg.org/people/index.html#sec-1-1][Werner]], [[https://gnupg.org/people/index.html#sec-1-3][Niibe]] or [[https://gnupg.org/people/index.html#sec-1-6][Andre]] to write
446 whatever was missing.  Perhaps even [[https://gnupg.org/people/index.html#sec-1-4][Jussi]], but there shouldn't be any
447 need for these bindings to interface directly with his work and for
448 much the same reasons as we recommend people not call libgcrypt
449 directly unless they know what they're doing.
450
451
452 * Fundamentals
453   :PROPERTIES:
454   :CUSTOM_ID: howto-fund-a-mental
455   :END:
456
457 Before we can get to the fun stuff, there are a few matters regarding
458 GPGME's design which hold true whether you're dealing with the C code
459 directly or these Python bindings.
460
461
462 ** No REST
463    :PROPERTIES:
464    :CUSTOM_ID: no-rest-for-the-wicked
465    :END:
466
467 The first part of which is or will be fairly blatantly obvious upon
468 viewing the first example, but it's worth reiterating anyway.  That
469 being that this API is /*not*/ a REST API.  Nor indeed could it ever
470 be one.
471
472 Most, if not all, Python programmers (and not just Python programmers)
473 know how easy it is to work with a RESTful API.  In fact they've
474 become so popular that many other APIs attempt to emulate REST-like
475 behaviour as much as they are able.  Right down to the use of JSON
476 formatted output to facilitate the use of their API without having to
477 retrain developers.
478
479 This API does not do that.  It would not be able to do that and also
480 provide access to the entire C API on which it's built.  It does,
481 however, provide a very pythonic interface on top of the direct
482 bindings and it's this pythonic layer that this HOWTO deals with.
483
484
485 ** Context
486    :PROPERTIES:
487    :CUSTOM_ID: howto-get-context
488    :END:
489
490 One of the reasons which prevents this API from being RESTful is that
491 most operations require more than one instruction to the API to
492 perform the task.  Sure, there are certain functions which can be
493 performed simultaneously, particularly if the result known or strongly
494 anticipated (e.g. selecting and encrypting to a key known to be in the
495 public keybox).
496
497 There are many more, however, which cannot be manipulated so readily:
498 they must be performed in a specific sequence and the result of one
499 operation has a direct bearing on the outcome of subsequent
500 operations.  Not merely by generating an error either.
501
502 When dealing with this type of persistent state on the web, full of
503 both the RESTful and REST-like, it's most commonly referred to as a
504 session.  In GPGME, however, it is called a context and every
505 operation type has one.
506
507
508 * Working with keys
509   :PROPERTIES:
510   :CUSTOM_ID: howto-keys
511   :END:
512
513
514 ** Key selection
515    :PROPERTIES:
516    :CUSTOM_ID: howto-keys-selection
517    :END:
518
519 Selecting keys to encrypt to or to sign with will be a common
520 occurrence when working with GPGMe and the means available for doing
521 so are quite simple.
522
523 They do depend on utilising a Context; however once the data is
524 recorded in another variable, that Context does not need to be the
525 same one which subsequent operations are performed.
526
527 The easiest way to select a specific key is by searching for that
528 key's key ID or fingerprint, preferably the full fingerprint without
529 any spaces in it.  A long key ID will probably be okay, but is not
530 advised and short key IDs are already a problem with some being
531 generated to match specific patterns.  It does not matter whether the
532 pattern is upper or lower case.
533
534 So this is the best method:
535
536 #+BEGIN_SRC python -i
537 import gpg
538
539 k = gpg.Context().keylist(pattern="258E88DCBD3CD44D8E7AB43F6ECB6AF0DEADBEEF")
540 keys = list(k)
541 #+END_SRC
542
543 This is passable and very likely to be common:
544
545 #+BEGIN_SRC python -i
546 import gpg
547
548 k = gpg.Context().keylist(pattern="0x6ECB6AF0DEADBEEF")
549 keys = list(k)
550 #+END_SRC
551
552 And this is a really bad idea:
553
554 #+BEGIN_SRC python -i
555 import gpg
556
557 k = gpg.Context().keylist(pattern="0xDEADBEEF")
558 keys = list(k)
559 #+END_SRC
560
561 Alternatively it may be that the intention is to create a list of keys
562 which all match a particular search string.  For instance all the
563 addresses at a particular domain, like this:
564
565 #+BEGIN_SRC python -i
566 import gpg
567
568 ncsc = gpg.Context().keylist(pattern="ncsc.mil")
569 nsa = list(ncsc)
570 #+END_SRC
571
572
573 *** Counting keys
574     :PROPERTIES:
575     :CUSTOM_ID: howto-keys-counting
576     :END:
577
578 Counting the number of keys in your public keybox (=pubring.kbx=), the
579 format which has superseded the old keyring format (=pubring.gpg= and
580 =secring.gpg=), or the number of secret keys is a very simple task.
581
582 #+BEGIN_SRC python -i
583 import gpg
584
585 c = gpg.Context()
586 seckeys = c.keylist(pattern=None, secret=True)
587 pubkeys = c.keylist(pattern=None, secret=False)
588
589 seclist = list(seckeys)
590 secnum = len(seclist)
591
592 publist = list(pubkeys)
593 pubnum = len(publist)
594
595 print("""
596   Number of secret keys:  {0}
597   Number of public keys:  {1}
598 """.format(secnum, pubnum))
599 #+END_SRC
600
601
602 ** Get key
603    :PROPERTIES:
604    :CUSTOM_ID: howto-get-key
605    :END:
606
607 An alternative method of getting a single key via its fingerprint is
608 available directly within a Context with =Context().get_key=.  This is
609 the preferred method of selecting a key in order to modify it, sign or
610 certify it and for obtaining relevant data about a single key as a
611 part of other functions; when verifying a signature made by that key,
612 for instance.
613
614 By default this method will select public keys, but it can select
615 secret keys as well.
616
617 This first example demonstrates selecting the current key of Werner
618 Koch, which is due to expire at the end of 2018:
619
620 #+BEGIN_SRC python -i
621 import gpg
622
623 fingerprint = "80615870F5BAD690333686D0F2AD85AC1E42B367"
624 key = gpg.Context().get_key(fingerprint)
625 #+END_SRC
626
627 Whereas this example demonstrates selecting the author's current key
628 with the =secret= key word argument set to =True=:
629
630 #+BEGIN_SRC python -i
631 import gpg
632
633 fingerprint = "DB4724E6FA4286C92B4E55C4321E4E2373590E5D"
634 key = gpg.Context().get_key(fingerprint, secret=True)
635 #+END_SRC
636
637 It is, of course, quite possible to select expired, disabled and
638 revoked keys with this function, but only to effectively display
639 information about those keys.
640
641 It is also possible to use both unicode or string literals and byte
642 literals with the fingerprint when getting a key in this way.
643
644
645 ** Importing keys
646    :PROPERTIES:
647    :CUSTOM_ID: howto-import-key
648    :END:
649
650 Importing keys is possible with the =key_import()= method and takes
651 one argument which is a bytes literal object containing either the
652 binary or ASCII armoured key data for one or more keys.
653
654 The following example retrieves one or more keys from the SKS
655 keyservers via the web using the requests module. Since requests
656 returns the content as a bytes literal object, we can then use that
657 directly to import the resulting data into our keybox.
658
659 #+BEGIN_SRC python -i
660 import gpg
661 import os.path
662 import requests
663
664 c = gpg.Context()
665 url = "https://sks-keyservers.net/pks/lookup"
666 pattern = input("Enter the pattern to search for key or user IDs: ")
667 payload = { "op": "get", "search": pattern }
668
669 r = requests.get(url, verify=True, params=payload)
670 result = c.key_import(r.content)
671
672 if result is not None and hasattr(result, "considered") is False:
673     print(result)
674 elif result is not None and hasattr(result, "considered") is True:
675     num_keys = len(result.imports)
676     new_revs = result.new_revocations
677     new_sigs = result.new_signatures
678     new_subs = result.new_sub_keys
679     new_uids = result.new_user_ids
680     new_scrt = result.secret_imported
681     nochange = result.unchanged
682     print("""
683   The total number of keys considered for import was:  {0}
684
685      Number of keys revoked:  {1}
686    Number of new signatures:  {2}
687       Number of new subkeys:  {3}
688      Number of new user IDs:  {4}
689   Number of new secret keys:  {5}
690    Number of unchanged keys:  {6}
691
692   The key IDs for all considered keys were:
693 """.format(num_keys, new_revs, new_sigs, new_subs, new_uids, new_scrt,
694            nochange))
695     for i in range(num_keys):
696         print("{0}\n".format(result.imports[i].fpr))
697 else:
698     pass
699 #+END_SRC
700
701 *NOTE:* When searching for a key ID of any length or a fingerprint
702 (without spaces), the SKS servers require the the leading =0x=
703 indicative of hexadecimal be included. Also note that the old short
704 key IDs (e.g. =0xDEADBEEF=) should no longer be used due to the
705 relative ease by which such key IDs can be reproduced, as demonstrated
706 by the Evil32 Project in 2014 (which was subsequently exploited in
707 2016).
708
709 Here is a variation on the above which checks the constrained
710 ProtonMail keyserver for ProtonMail public keys.
711
712 #+BEGIN_SRC python -i
713 import gpg
714 import requests
715 import sys
716
717 print("""
718 This script searches the ProtonMail key server for the specified key and
719 imports it.
720 """)
721
722 c = gpg.Context(armor=True)
723 url = "https://api.protonmail.ch/pks/lookup"
724 ksearch = []
725
726 if len(sys.argv) >= 2:
727     keyterm = sys.argv[1]
728 else:
729     keyterm = input("Enter the key ID, UID or search string: ")
730
731 if keyterm.count("@") == 2 and keyterm.startswith("@") is True:
732     ksearch.append(keyterm[1:])
733     ksearch.append(keyterm[1:])
734     ksearch.append(keyterm[1:])
735 elif keyterm.count("@") == 1 and keyterm.startswith("@") is True:
736     ksearch.append("{0}@protonmail.com".format(keyterm[1:]))
737     ksearch.append("{0}@protonmail.ch".format(keyterm[1:]))
738     ksearch.append("{0}@pm.me".format(keyterm[1:]))
739 elif keyterm.count("@") == 0:
740     ksearch.append("{0}@protonmail.com".format(keyterm))
741     ksearch.append("{0}@protonmail.ch".format(keyterm))
742     ksearch.append("{0}@pm.me".format(keyterm))
743 elif keyterm.count("@") == 2 and keyterm.startswith("@") is False:
744     uidlist = keyterm.split("@")
745     for uid in uidlist:
746         ksearch.append("{0}@protonmail.com".format(uid))
747         ksearch.append("{0}@protonmail.ch".format(uid))
748         ksearch.append("{0}@pm.me".format(uid))
749 elif keyterm.count("@") > 2:
750     uidlist = keyterm.split("@")
751     for uid in uidlist:
752         ksearch.append("{0}@protonmail.com".format(uid))
753         ksearch.append("{0}@protonmail.ch".format(uid))
754         ksearch.append("{0}@pm.me".format(uid))
755 else:
756     ksearch.append(keyterm)
757
758 for k in ksearch:
759     payload = {"op": "get", "search": k}
760     try:
761         r = requests.get(url, verify=True, params=payload)
762         if r.ok is True:
763             result = c.key_import(r.content)
764         elif r.ok is False:
765             result = r.content
766     except Exception as e:
767         result = None
768
769     if result is not None and hasattr(result, "considered") is False:
770         print("{0} for {1}".format(result.decode(), k))
771     elif result is not None and hasattr(result, "considered") is True:
772         num_keys = len(result.imports)
773         new_revs = result.new_revocations
774         new_sigs = result.new_signatures
775         new_subs = result.new_sub_keys
776         new_uids = result.new_user_ids
777         new_scrt = result.secret_imported
778         nochange = result.unchanged
779         print("""
780 The total number of keys considered for import was:  {0}
781
782 With UIDs wholely or partially matching the following string:
783
784         {1}
785
786    Number of keys revoked:  {2}
787  Number of new signatures:  {3}
788     Number of new subkeys:  {4}
789    Number of new user IDs:  {5}
790 Number of new secret keys:  {6}
791  Number of unchanged keys:  {7}
792
793 The key IDs for all considered keys were:
794 """.format(num_keys, k, new_revs, new_sigs, new_subs, new_uids, new_scrt,
795            nochange))
796         for i in range(num_keys):
797             print(result.imports[i].fpr)
798         print("")
799     elif result is None:
800         print(e)
801 #+END_SRC
802
803 Both the above example, [[../examples/howto/pmkey-import.py][pmkey-import.py]], and a version which prompts
804 for an alternative GnuPG home directory, [[../examples/howto/pmkey-import-alt.py][pmkey-import-alt.py]], are
805 available with the other examples and are executable scripts.
806
807 Note that while the ProtonMail servers are based on the SKS servers,
808 their server is related more to their API and is not feature complete
809 by comparison to the servers in the SKS pool.  One notable difference
810 being that the ProtonMail server does not permit non ProtonMail users
811 to update their own keys, which could be a vector for attacking
812 ProtonMail users who may not receive a key's revocation if it had been
813 compromised.
814
815
816 ** Exporting keys
817    :PROPERTIES:
818    :CUSTOM_ID: howto-export-key
819    :END:
820
821 Exporting keys remains a reasonably simple task, but has been
822 separated into three different functions for the OpenPGP cryptographic
823 engine.  Two of those functions are for exporting public keys and the
824 third is for exporting secret keys.
825
826
827 *** Exporting public keys
828     :PROPERTIES:
829     :CUSTOM_ID: howto-export-public-key
830     :END:
831
832 There are two methods of exporting public keys, both of which are very
833 similar to the other.  The default method, =key_export()=, will export
834 a public key or keys matching a specified pattern as normal.  The
835 alternative, the =key_export_minimal()= method, will do the same thing
836 except producing a minimised output with extra signatures and third
837 party signatures or certifications removed.
838
839 #+BEGIN_SRC python -i
840 import gpg
841 import os.path
842 import sys
843
844 print("""
845 This script exports one or more public keys.
846 """)
847
848 c = gpg.Context(armor=True)
849
850 if len(sys.argv) >= 4:
851     keyfile = sys.argv[1]
852     logrus = sys.argv[2]
853     homedir = sys.argv[3]
854 elif len(sys.argv) == 3:
855     keyfile = sys.argv[1]
856     logrus = sys.argv[2]
857     homedir = input("Enter the GPG configuration directory path (optional): ")
858 elif len(sys.argv) == 2:
859     keyfile = sys.argv[1]
860     logrus = input("Enter the UID matching the key(s) to export: ")
861     homedir = input("Enter the GPG configuration directory path (optional): ")
862 else:
863     keyfile = input("Enter the path and filename to save the secret key to: ")
864     logrus = input("Enter the UID matching the key(s) to export: ")
865     homedir = input("Enter the GPG configuration directory path (optional): ")
866
867 if homedir.startswith("~"):
868     if os.path.exists(os.path.expanduser(homedir)) is True:
869         c.home_dir = os.path.expanduser(homedir)
870     else:
871         pass
872 elif os.path.exists(homedir) is True:
873     c.home_dir = homedir
874 else:
875     pass
876
877 try:
878     result = c.key_export(pattern=logrus)
879 except:
880     result = c.key_export(pattern=None)
881
882 if result is not None:
883     with open(keyfile, "wb") as f:
884         f.write(result)
885 else:
886     pass
887 #+END_SRC
888
889 It is important to note that the result will only return =None= when a
890 pattern has been entered for =logrus=, but it has not matched any
891 keys. When the search pattern itself is set to =None= this triggers
892 the exporting of the entire public keybox.
893
894 #+BEGIN_SRC python -i
895 import gpg
896 import os.path
897 import sys
898
899 print("""
900 This script exports one or more public keys in minimised form.
901 """)
902
903 c = gpg.Context(armor=True)
904
905 if len(sys.argv) >= 4:
906     keyfile = sys.argv[1]
907     logrus = sys.argv[2]
908     homedir = sys.argv[3]
909 elif len(sys.argv) == 3:
910     keyfile = sys.argv[1]
911     logrus = sys.argv[2]
912     homedir = input("Enter the GPG configuration directory path (optional): ")
913 elif len(sys.argv) == 2:
914     keyfile = sys.argv[1]
915     logrus = input("Enter the UID matching the key(s) to export: ")
916     homedir = input("Enter the GPG configuration directory path (optional): ")
917 else:
918     keyfile = input("Enter the path and filename to save the secret key to: ")
919     logrus = input("Enter the UID matching the key(s) to export: ")
920     homedir = input("Enter the GPG configuration directory path (optional): ")
921
922 if homedir.startswith("~"):
923     if os.path.exists(os.path.expanduser(homedir)) is True:
924         c.home_dir = os.path.expanduser(homedir)
925     else:
926         pass
927 elif os.path.exists(homedir) is True:
928     c.home_dir = homedir
929 else:
930     pass
931
932 try:
933     result = c.key_export_minimal(pattern=logrus)
934 except:
935     result = c.key_export_minimal(pattern=None)
936
937 if result is not None:
938     with open(keyfile, "wb") as f:
939         f.write(result)
940 else:
941     pass
942 #+END_SRC
943
944
945 *** Exporting secret keys
946     :PROPERTIES:
947     :CUSTOM_ID: howto-export-secret-key
948     :END:
949
950 Exporting secret keys is, functionally, very similar to exporting
951 public keys; save for the invocation of =pinentry= via =gpg-agent= in
952 order to securely enter the key's passphrase and authorise the export.
953
954 The following example exports the secret key to a file which is then
955 set with the same permissions as the output files created by the
956 command line secret key export options.
957
958 #+BEGIN_SRC python -i
959 import gpg
960 import os
961 import os.path
962 import sys
963
964 print("""
965 This script exports one or more secret keys.
966
967 The gpg-agent and pinentry are invoked to authorise the export.
968 """)
969
970 c = gpg.Context(armor=True)
971
972 if len(sys.argv) >= 4:
973     keyfile = sys.argv[1]
974     logrus = sys.argv[2]
975     homedir = sys.argv[3]
976 elif len(sys.argv) == 3:
977     keyfile = sys.argv[1]
978     logrus = sys.argv[2]
979     homedir = input("Enter the GPG configuration directory path (optional): ")
980 elif len(sys.argv) == 2:
981     keyfile = sys.argv[1]
982     logrus = input("Enter the UID matching the secret key(s) to export: ")
983     homedir = input("Enter the GPG configuration directory path (optional): ")
984 else:
985     keyfile = input("Enter the path and filename to save the secret key to: ")
986     logrus = input("Enter the UID matching the secret key(s) to export: ")
987     homedir = input("Enter the GPG configuration directory path (optional): ")
988
989 if homedir.startswith("~"):
990     if os.path.exists(os.path.expanduser(homedir)) is True:
991         c.home_dir = os.path.expanduser(homedir)
992     else:
993         pass
994 elif os.path.exists(homedir) is True:
995     c.home_dir = homedir
996 else:
997     pass
998
999 try:
1000     result = c.key_export_secret(pattern=logrus)
1001 except:
1002     result = c.key_export_secret(pattern=None)
1003
1004 if result is not None:
1005     with open(keyfile, "wb") as f:
1006         f.write(result)
1007     os.chmod(keyfile, 0o600)
1008 else:
1009     pass
1010 #+END_SRC
1011
1012 Alternatively the approach of the following script can be used.  This
1013 longer example saves the exported secret key(s) in files in the GnuPG
1014 home directory, in addition to setting the file permissions as only
1015 readable and writable by the user.  It also exports the secret key(s)
1016 twice in order to output both GPG binary (=.gpg=) and ASCII armoured
1017 (=.asc=) files.
1018
1019 #+BEGIN_SRC python -i
1020 import gpg
1021 import os
1022 import os.path
1023 import subprocess
1024 import sys
1025
1026 print("""
1027 This script exports one or more secret keys as both ASCII armored and binary
1028 file formats, saved in files within the user's GPG home directory.
1029
1030 The gpg-agent and pinentry are invoked to authorise the export.
1031 """)
1032
1033 if sys.platform == "win32":
1034     gpgconfcmd = "gpgconf.exe --list-dirs homedir"
1035 else:
1036     gpgconfcmd = "gpgconf --list-dirs homedir"
1037
1038 a = gpg.Context(armor=True)
1039 b = gpg.Context()
1040 c = gpg.Context()
1041
1042 if len(sys.argv) >= 4:
1043     keyfile = sys.argv[1]
1044     logrus = sys.argv[2]
1045     homedir = sys.argv[3]
1046 elif len(sys.argv) == 3:
1047     keyfile = sys.argv[1]
1048     logrus = sys.argv[2]
1049     homedir = input("Enter the GPG configuration directory path (optional): ")
1050 elif len(sys.argv) == 2:
1051     keyfile = sys.argv[1]
1052     logrus = input("Enter the UID matching the secret key(s) to export: ")
1053     homedir = input("Enter the GPG configuration directory path (optional): ")
1054 else:
1055     keyfile = input("Enter the filename to save the secret key to: ")
1056     logrus = input("Enter the UID matching the secret key(s) to export: ")
1057     homedir = input("Enter the GPG configuration directory path (optional): ")
1058
1059 if homedir.startswith("~"):
1060     if os.path.exists(os.path.expanduser(homedir)) is True:
1061         c.home_dir = os.path.expanduser(homedir)
1062     else:
1063         pass
1064 elif os.path.exists(homedir) is True:
1065     c.home_dir = homedir
1066 else:
1067     pass
1068
1069 if c.home_dir is not None:
1070     if c.home_dir.endswith("/"):
1071         gpgfile = "{0}{1}.gpg".format(c.home_dir, keyfile)
1072         ascfile = "{0}{1}.asc".format(c.home_dir, keyfile)
1073     else:
1074         gpgfile = "{0}/{1}.gpg".format(c.home_dir, keyfile)
1075         ascfile = "{0}/{1}.asc".format(c.home_dir, keyfile)
1076 else:
1077     if os.path.exists(os.environ["GNUPGHOME"]) is True:
1078         hd = os.environ["GNUPGHOME"]
1079     else:
1080         try:
1081             hd = subprocess.getoutput(gpgconfcmd)
1082         except:
1083             process = subprocess.Popen(gpgconfcmd.split(),
1084                                        stdout=subprocess.PIPE)
1085             procom = process.communicate()
1086             if sys.version_info[0] == 2:
1087                 hd = procom[0].strip()
1088             else:
1089                 hd = procom[0].decode().strip()
1090     gpgfile = "{0}/{1}.gpg".format(hd, keyfile)
1091     ascfile = "{0}/{1}.asc".format(hd, keyfile)
1092
1093 try:
1094     a_result = a.key_export_secret(pattern=logrus)
1095     b_result = b.key_export_secret(pattern=logrus)
1096 except:
1097     a_result = a.key_export_secret(pattern=None)
1098     b_result = b.key_export_secret(pattern=None)
1099
1100 if a_result is not None:
1101     with open(ascfile, "wb") as f:
1102         f.write(a_result)
1103     os.chmod(ascfile, 0o600)
1104 else:
1105     pass
1106
1107 if b_result is not None:
1108     with open(gpgfile, "wb") as f:
1109         f.write(b_result)
1110     os.chmod(gpgfile, 0o600)
1111 else:
1112     pass
1113 #+END_SRC
1114
1115
1116 * Basic Functions
1117   :PROPERTIES:
1118   :CUSTOM_ID: howto-the-basics
1119   :END:
1120
1121 The most frequently called features of any cryptographic library will
1122 be the most fundamental tasks for encryption software.  In this
1123 section we will look at how to programmatically encrypt data, decrypt
1124 it, sign it and verify signatures.
1125
1126
1127 ** Encryption
1128    :PROPERTIES:
1129    :CUSTOM_ID: howto-basic-encryption
1130    :END:
1131
1132 Encrypting is very straight forward.  In the first example below the
1133 message, =text=, is encrypted to a single recipient's key.  In the
1134 second example the message will be encrypted to multiple recipients.
1135
1136
1137 *** Encrypting to one key
1138     :PROPERTIES:
1139     :CUSTOM_ID: howto-basic-encryption-single
1140     :END:
1141
1142 Once the the Context is set the main issues with encrypting data is
1143 essentially reduced to key selection and the keyword arguments
1144 specified in the =gpg.Context().encrypt()= method.
1145
1146 Those keyword arguments are: =recipients=, a list of keys encrypted to
1147 (covered in greater detail in the following section); =sign=, whether
1148 or not to sign the plaintext data, see subsequent sections on signing
1149 and verifying signatures below (defaults to =True=); =sink=, to write
1150 results or partial results to a secure sink instead of returning it
1151 (defaults to =None=); =passphrase=, only used when utilising symmetric
1152 encryption (defaults to =None=); =always_trust=, used to override the
1153 trust model settings for recipient keys (defaults to =False=);
1154 =add_encrypt_to=, utilises any preconfigured =encrypt-to= or
1155 =default-key= settings in the user's =gpg.conf= file (defaults to
1156 =False=); =prepare=, prepare for encryption (defaults to =False=);
1157 =expect_sign=, prepare for signing (defaults to =False=); =compress=,
1158 compresses the plaintext prior to encryption (defaults to =True=).
1159
1160 #+BEGIN_SRC python -i
1161 import gpg
1162
1163 a_key = "0x12345678DEADBEEF"
1164 text = b"""Some text to test with.
1165
1166 Since the text in this case must be bytes, it is most likely that
1167 the input form will be a separate file which is opened with "rb"
1168 as this is the simplest method of obtaining the correct data format.
1169 """
1170
1171 c = gpg.Context(armor=True)
1172 rkey = list(c.keylist(pattern=a_key, secret=False))
1173 ciphertext, result, sign_result = c.encrypt(text, recipients=rkey, sign=False)
1174
1175 with open("secret_plans.txt.asc", "wb") as afile:
1176     afile.write(ciphertext)
1177 #+END_SRC
1178
1179 Though this is even more likely to be used like this; with the
1180 plaintext input read from a file, the recipient keys used for
1181 encryption regardless of key trust status and the encrypted output
1182 also encrypted to any preconfigured keys set in the =gpg.conf= file:
1183
1184 #+BEGIN_SRC python -i
1185 import gpg
1186
1187 a_key = "0x12345678DEADBEEF"
1188
1189 with open("secret_plans.txt", "rb") as afile:
1190     text = afile.read()
1191
1192 c = gpg.Context(armor=True)
1193 rkey = list(c.keylist(pattern=a_key, secret=False))
1194 ciphertext, result, sign_result = c.encrypt(text, recipients=rkey, sign=True,
1195                                             always_trust=True,
1196                                             add_encrypt_to=True)
1197
1198 with open("secret_plans.txt.asc", "wb") as afile:
1199     afile.write(ciphertext)
1200 #+END_SRC
1201
1202 If the =recipients= paramater is empty then the plaintext is encrypted
1203 symmetrically.  If no =passphrase= is supplied as a parameter or via a
1204 callback registered with the =Context()= then an out-of-band prompt
1205 for the passphrase via pinentry will be invoked.
1206
1207
1208 *** Encrypting to multiple keys
1209     :PROPERTIES:
1210     :CUSTOM_ID: howto-basic-encryption-multiple
1211     :END:
1212
1213 Encrypting to multiple keys essentially just expands upon the key
1214 selection process and the recipients from the previous examples.
1215
1216 The following example encrypts a message (=text=) to everyone with an
1217 email address on the =gnupg.org= domain,[fn:5] but does /not/ encrypt
1218 to a default key or other key which is configured to normally encrypt
1219 to.
1220
1221 #+BEGIN_SRC python -i
1222 import gpg
1223
1224 text = b"""Oh look, another test message.
1225
1226 The same rules apply as with the previous example and more likely
1227 than not, the message will actually be drawn from reading the
1228 contents of a file or, maybe, from entering data at an input()
1229 prompt.
1230
1231 Since the text in this case must be bytes, it is most likely that
1232 the input form will be a separate file which is opened with "rb"
1233 as this is the simplest method of obtaining the correct data
1234 format.
1235 """
1236
1237 c = gpg.Context(armor=True)
1238 rpattern = list(c.keylist(pattern="@gnupg.org", secret=False))
1239 logrus = []
1240
1241 for i in range(len(rpattern)):
1242     if rpattern[i].can_encrypt == 1:
1243         logrus.append(rpattern[i])
1244
1245 ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
1246                                             sign=False, always_trust=True)
1247
1248 with open("secret_plans.txt.asc", "wb") as afile:
1249     afile.write(ciphertext)
1250 #+END_SRC
1251
1252 All it would take to change the above example to sign the message
1253 and also encrypt the message to any configured default keys would
1254 be to change the =c.encrypt= line to this:
1255
1256 #+BEGIN_SRC python -i
1257 ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
1258                                             always_trust=True,
1259                                             add_encrypt_to=True)
1260 #+END_SRC
1261
1262 The only keyword arguments requiring modification are those for which
1263 the default values are changing.  The default value of =sign= is
1264 =True=, the default of =always_trust= is =False=, the default of
1265 =add_encrypt_to= is =False=.
1266
1267 If =always_trust= is not set to =True= and any of the recipient keys
1268 are not trusted (e.g. not signed or locally signed) then the
1269 encryption will raise an error.  It is possible to mitigate this
1270 somewhat with something more like this:
1271
1272 #+BEGIN_SRC python -i
1273 import gpg
1274
1275 with open("secret_plans.txt.asc", "rb") as afile:
1276     text = afile.read()
1277
1278 c = gpg.Context(armor=True)
1279 rpattern = list(c.keylist(pattern="@gnupg.org", secret=False))
1280 logrus = []
1281
1282 for i in range(len(rpattern)):
1283     if rpattern[i].can_encrypt == 1:
1284         logrus.append(rpattern[i])
1285
1286     try:
1287         ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
1288                                                     add_encrypt_to=True)
1289     except gpg.errors.InvalidRecipients as e:
1290         for i in range(len(e.recipients)):
1291             for n in range(len(logrus)):
1292                 if logrus[n].fpr == e.recipients[i].fpr:
1293                     logrus.remove(logrus[n])
1294                 else:
1295                     pass
1296         try:
1297             ciphertext, result, sign_result = c.encrypt(text,
1298                                                         recipients=logrus,
1299                                                         add_encrypt_to=True)
1300             with open("secret_plans.txt.asc", "wb") as afile:
1301                 afile.write(ciphertext)
1302         except:
1303             pass
1304 #+END_SRC
1305
1306 This will attempt to encrypt to all the keys searched for, then remove
1307 invalid recipients if it fails and try again.
1308
1309
1310 ** Decryption
1311    :PROPERTIES:
1312    :CUSTOM_ID: howto-basic-decryption
1313    :END:
1314
1315 Decrypting something encrypted to a key in one's secret keyring is
1316 fairly straight forward.
1317
1318 In this example code, however, preconfiguring either =gpg.Context()=
1319 or =gpg.core.Context()= as =c= is unnecessary because there is no need
1320 to modify the Context prior to conducting the decryption and since the
1321 Context is only used once, setting it to =c= simply adds lines for no
1322 gain.
1323
1324 #+BEGIN_SRC python -i
1325 import gpg
1326
1327 ciphertext = input("Enter path and filename of encrypted file: ")
1328 newfile = input("Enter path and filename of file to save decrypted data to: ")
1329
1330 with open(ciphertext, "rb") as cfile:
1331     try:
1332         plaintext, result, verify_result = gpg.Context().decrypt(cfile)
1333     except gpg.errors.GPGMEError as e:
1334         plaintext = None
1335         print(e)
1336
1337 if plaintext is not None:
1338     with open(newfile, "wb") as nfile:
1339             nfile.write(plaintext)
1340     else:
1341         pass
1342 #+END_SRC
1343
1344 The data available in =plaintext= in this example is the decrypted
1345 content as a byte object, the recipient key IDs and algorithms in
1346 =result= and the results of verifying any signatures of the data in
1347 =verify_result=.
1348
1349
1350 ** Signing text and files
1351    :PROPERTIES:
1352    :CUSTOM_ID: howto-basic-signing
1353    :END:
1354
1355 The following sections demonstrate how to specify keys to sign with.
1356
1357
1358 *** Signing key selection
1359     :PROPERTIES:
1360     :CUSTOM_ID: howto-basic-signing-signers
1361     :END:
1362
1363 By default GPGME and the Python bindings will use the default key
1364 configured for the user invoking the GPGME API.  If there is no
1365 default key specified and there is more than one secret key available
1366 it may be necessary to specify the key or keys with which to sign
1367 messages and files.
1368
1369 #+BEGIN_SRC python -i
1370 import gpg
1371
1372 logrus = input("Enter the email address or string to match signing keys to: ")
1373 hancock = gpg.Context().keylist(pattern=logrus, secret=True)
1374 sig_src = list(hancock)
1375 #+END_SRC
1376
1377 The signing examples in the following sections include the explicitly
1378 designated =signers= parameter in two of the five examples; once where
1379 the resulting signature would be ASCII armoured and once where it
1380 would not be armoured.
1381
1382 While it would be possible to enter a key ID or fingerprint here to
1383 match a specific key, it is not possible to enter two fingerprints and
1384 match two keys since the patten expects a string, bytes or None and
1385 not a list.  A string with two fingerprints won't match any single
1386 key.
1387
1388
1389 *** Normal or default signing messages or files
1390     :PROPERTIES:
1391     :CUSTOM_ID: howto-basic-signing-normal
1392     :END:
1393
1394 The normal or default signing process is essentially the same as is
1395 most often invoked when also encrypting a message or file.  So when
1396 the encryption component is not utilised, the result is to produce an
1397 encoded and signed output which may or may not be ASCII armoured and
1398 which may or may not also be compressed.
1399
1400 By default compression will be used unless GnuPG detects that the
1401 plaintext is already compressed.  ASCII armouring will be determined
1402 according to the value of =gpg.Context().armor=.
1403
1404 The compression algorithm is selected in much the same way as the
1405 symmetric encryption algorithm or the hash digest algorithm is when
1406 multiple keys are involved; from the preferences saved into the key
1407 itself or by comparison with the preferences with all other keys
1408 involved.
1409
1410 #+BEGIN_SRC python -i
1411 import gpg
1412
1413 text0 = """Declaration of ... something.
1414
1415 """
1416 text = text0.encode()
1417
1418 c = gpg.Context(armor=True, signers=sig_src)
1419 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.NORMAL)
1420
1421 with open("/path/to/statement.txt.asc", "w") as afile:
1422     afile.write(signed_data.decode())
1423 #+END_SRC
1424
1425 Though everything in this example is accurate, it is more likely that
1426 reading the input data from another file and writing the result to a
1427 new file will be performed more like the way it is done in the next
1428 example.  Even if the output format is ASCII armoured.
1429
1430 #+BEGIN_SRC python -i
1431 import gpg
1432
1433 with open("/path/to/statement.txt", "rb") as tfile:
1434     text = tfile.read()
1435
1436 c = gpg.Context()
1437 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.NORMAL)
1438
1439 with open("/path/to/statement.txt.sig", "wb") as afile:
1440     afile.write(signed_data)
1441 #+END_SRC
1442
1443
1444 *** Detached signing messages and files
1445     :PROPERTIES:
1446     :CUSTOM_ID: howto-basic-signing-detached
1447     :END:
1448
1449 Detached signatures will often be needed in programmatic uses of
1450 GPGME, either for signing files (e.g. tarballs of code releases) or as
1451 a component of message signing (e.g. PGP/MIME encoded email).
1452
1453 #+BEGIN_SRC python -i
1454 import gpg
1455
1456 text0 = """Declaration of ... something.
1457
1458 """
1459 text = text0.encode()
1460
1461 c = gpg.Context(armor=True)
1462 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.DETACH)
1463
1464 with open("/path/to/statement.txt.asc", "w") as afile:
1465     afile.write(signed_data.decode())
1466 #+END_SRC
1467
1468 As with normal signatures, detached signatures are best handled as
1469 byte literals, even when the output is ASCII armoured.
1470
1471 #+BEGIN_SRC python -i
1472 import gpg
1473
1474 with open("/path/to/statement.txt", "rb") as tfile:
1475     text = tfile.read()
1476
1477 c = gpg.Context(signers=sig_src)
1478 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.DETACH)
1479
1480 with open("/path/to/statement.txt.sig", "wb") as afile:
1481     afile.write(signed_data)
1482 #+END_SRC
1483
1484
1485 *** Clearsigning messages or text
1486     :PROPERTIES:
1487     :CUSTOM_ID: howto-basic-signing-clear
1488     :END:
1489
1490 Though PGP/in-line messages are no longer encouraged in favour of
1491 PGP/MIME, there is still sometimes value in utilising in-line
1492 signatures.  This is where clear-signed messages or text is of value.
1493
1494 #+BEGIN_SRC python -i
1495 import gpg
1496
1497 text0 = """Declaration of ... something.
1498
1499 """
1500 text = text0.encode()
1501
1502 c = gpg.Context()
1503 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.CLEAR)
1504
1505 with open("/path/to/statement.txt.asc", "w") as afile:
1506     afile.write(signed_data.decode())
1507 #+END_SRC
1508
1509 In spite of the appearance of a clear-signed message, the data handled
1510 by GPGME in signing it must still be byte literals.
1511
1512 #+BEGIN_SRC python -i
1513 import gpg
1514
1515 with open("/path/to/statement.txt", "rb") as tfile:
1516     text = tfile.read()
1517
1518 c = gpg.Context()
1519 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.CLEAR)
1520
1521 with open("/path/to/statement.txt.asc", "wb") as afile:
1522     afile.write(signed_data)
1523 #+END_SRC
1524
1525
1526 ** Signature verification
1527    :PROPERTIES:
1528    :CUSTOM_ID: howto-basic-verification
1529    :END:
1530
1531 Essentially there are two principal methods of verification of a
1532 signature.  The first of these is for use with the normal or default
1533 signing method and for clear-signed messages.  The second is for use
1534 with files and data with detached signatures.
1535
1536 The following example is intended for use with the default signing
1537 method where the file was not ASCII armoured:
1538
1539 #+BEGIN_SRC python -i
1540 import gpg
1541 import time
1542
1543 filename = "statement.txt"
1544 gpg_file = "statement.txt.gpg"
1545
1546 c = gpg.Context()
1547
1548 try:
1549     data, result = c.verify(open(gpg_file))
1550     verified = True
1551 except gpg.errors.BadSignatures as e:
1552     verified = False
1553     print(e)
1554
1555 if verified is True:
1556     for i in range(len(result.signatures)):
1557         sign = result.signatures[i]
1558         print("""Good signature from:
1559 {0}
1560 with key {1}
1561 made at {2}
1562 """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
1563            time.ctime(sign.timestamp)))
1564 else:
1565     pass
1566 #+END_SRC
1567
1568 Whereas this next example, which is almost identical would work with
1569 normal ASCII armoured files and with clear-signed files:
1570
1571 #+BEGIN_SRC python -i
1572 import gpg
1573 import time
1574
1575 filename = "statement.txt"
1576 asc_file = "statement.txt.asc"
1577
1578 c = gpg.Context()
1579
1580 try:
1581     data, result = c.verify(open(asc_file))
1582     verified = True
1583 except gpg.errors.BadSignatures as e:
1584     verified = False
1585     print(e)
1586
1587 if verified is True:
1588     for i in range(len(result.signatures)):
1589         sign = result.signatures[i]
1590         print("""Good signature from:
1591 {0}
1592 with key {1}
1593 made at {2}
1594 """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
1595            time.ctime(sign.timestamp)))
1596 else:
1597     pass
1598 #+END_SRC
1599
1600 In both of the previous examples it is also possible to compare the
1601 original data that was signed against the signed data in =data= to see
1602 if it matches with something like this:
1603
1604 #+BEGIN_SRC python -i
1605 with open(filename, "rb") as afile:
1606     text = afile.read()
1607
1608 if text == data:
1609     print("Good signature.")
1610 else:
1611     pass
1612 #+END_SRC
1613
1614 The following two examples, however, deal with detached signatures.
1615 With his method of verification the data that was signed does not get
1616 returned since it is already being explicitly referenced in the first
1617 argument of =c.verify=.  So =data= is =None= and only the information
1618 in =result= is available.
1619
1620 #+BEGIN_SRC python -i
1621 import gpg
1622 import time
1623
1624 filename = "statement.txt"
1625 sig_file = "statement.txt.sig"
1626
1627 c = gpg.Context()
1628
1629 try:
1630     data, result = c.verify(open(filename), open(sig_file))
1631     verified = True
1632 except gpg.errors.BadSignatures as e:
1633     verified = False
1634     print(e)
1635
1636 if verified is True:
1637     for i in range(len(result.signatures)):
1638         sign = result.signatures[i]
1639         print("""Good signature from:
1640 {0}
1641 with key {1}
1642 made at {2}
1643 """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
1644            time.ctime(sign.timestamp)))
1645 else:
1646     pass
1647 #+END_SRC
1648
1649 #+BEGIN_SRC python -i
1650 import gpg
1651 import time
1652
1653 filename = "statement.txt"
1654 asc_file = "statement.txt.asc"
1655
1656 c = gpg.Context()
1657
1658 try:
1659     data, result = c.verify(open(filename), open(asc_file))
1660     verified = True
1661 except gpg.errors.BadSignatures as e:
1662     verified = False
1663     print(e)
1664
1665 if verified is True:
1666     for i in range(len(result.signatures)):
1667         sign = result.signatures[i]
1668         print("""Good signature from:
1669 {0}
1670 with key {1}
1671 made at {2}
1672 """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
1673            time.ctime(sign.timestamp)))
1674 else:
1675     pass
1676 #+END_SRC
1677
1678
1679 * Creating keys and subkeys
1680   :PROPERTIES:
1681   :CUSTOM_ID: key-generation
1682   :END:
1683
1684 The one thing, aside from GnuPG itself, that GPGME depends on, of
1685 course, is the keys themselves.  So it is necessary to be able to
1686 generate them and modify them by adding subkeys, revoking or disabling
1687 them, sometimes deleting them and doing the same for user IDs.
1688
1689 In the following examples a key will be created for the world's
1690 greatest secret agent, Danger Mouse.  Since Danger Mouse is a secret
1691 agent he needs to be able to protect information to =SECRET= level
1692 clearance, so his keys will be 3072-bit keys.
1693
1694 The pre-configured =gpg.conf= file which sets cipher, digest and other
1695 preferences contains the following configuration parameters:
1696
1697 #+BEGIN_SRC conf
1698   expert
1699   allow-freeform-uid
1700   allow-secret-key-import
1701   trust-model tofu+pgp
1702   tofu-default-policy unknown
1703   enable-large-rsa
1704   enable-dsa2
1705   cert-digest-algo SHA512
1706   default-preference-list TWOFISH CAMELLIA256 AES256 CAMELLIA192 AES192 CAMELLIA128 AES BLOWFISH IDEA CAST5 3DES SHA512 SHA384 SHA256 SHA224 RIPEMD160 SHA1 ZLIB BZIP2 ZIP Uncompressed
1707   personal-cipher-preferences TWOFISH CAMELLIA256 AES256 CAMELLIA192 AES192 CAMELLIA128 AES BLOWFISH IDEA CAST5 3DES
1708   personal-digest-preferences SHA512 SHA384 SHA256 SHA224 RIPEMD160 SHA1
1709   personal-compress-preferences ZLIB BZIP2 ZIP Uncompressed
1710 #+END_SRC
1711
1712
1713 ** Primary key
1714    :PROPERTIES:
1715    :CUSTOM_ID: keygen-primary
1716    :END:
1717
1718 Generating a primary key uses the =create_key= method in a Context.
1719 It contains multiple arguments and keyword arguments, including:
1720 =userid=, =algorithm=, =expires_in=, =expires=, =sign=, =encrypt=,
1721 =certify=, =authenticate=, =passphrase= and =force=.  The defaults for
1722 all of those except =userid=, =algorithm=, =expires_in=, =expires= and
1723 =passphrase= is =False=.  The defaults for =algorithm= and
1724 =passphrase= is =None=.  The default for =expires_in= is =0=.  The
1725 default for =expires= is =True=.  There is no default for =userid=.
1726
1727 If =passphrase= is left as =None= then the key will not be generated
1728 with a passphrase, if =passphrase= is set to a string then that will
1729 be the passphrase and if =passphrase= is set to =True= then gpg-agent
1730 will launch pinentry to prompt for a passphrase.  For the sake of
1731 convenience, these examples will keep =passphrase= set to =None=.
1732
1733 #+BEGIN_SRC python -i
1734 import gpg
1735
1736 c = gpg.Context()
1737
1738 c.home_dir = "~/.gnupg-dm"
1739 userid = "Danger Mouse <dm@secret.example.net>"
1740
1741 dmkey = c.create_key(userid, algorithm="rsa3072", expires_in=31536000,
1742                      sign=True, certify=True)
1743 #+END_SRC
1744
1745 One thing to note here is the use of setting the =c.home_dir=
1746 parameter.  This enables generating the key or keys in a different
1747 location.  In this case to keep the new key data created for this
1748 example in a separate location rather than adding it to existing and
1749 active key store data.  As with the default directory, =~/.gnupg=, any
1750 temporary or separate directory needs the permissions set to only
1751 permit access by the directory owner.  On posix systems this means
1752 setting the directory permissions to 700.
1753
1754 The =temp-homedir-config.py= script in the HOWTO examples directory
1755 will create an alternative homedir with these configuration options
1756 already set and the correct directory and file permissions.
1757
1758 The successful generation of the key can be confirmed via the returned
1759 =GenkeyResult= object, which includes the following data:
1760
1761 #+BEGIN_SRC python -i
1762 print("""
1763  Fingerprint:  {0}
1764  Primary Key:  {1}
1765   Public Key:  {2}
1766   Secret Key:  {3}
1767  Sub Key:  {4}
1768 User IDs:  {5}
1769 """.format(dmkey.fpr, dmkey.primary, dmkey.pubkey, dmkey.seckey, dmkey.sub,
1770            dmkey.uid))
1771 #+END_SRC
1772
1773 Alternatively the information can be confirmed using the command line
1774 program:
1775
1776 #+BEGIN_SRC shell
1777   bash-4.4$ gpg --homedir ~/.gnupg-dm -K
1778   ~/.gnupg-dm/pubring.kbx
1779   ----------------------
1780   sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
1781         177B7C25DB99745EE2EE13ED026D2F19E99E63AA
1782   uid           [ultimate] Danger Mouse <dm@secret.example.net>
1783
1784   bash-4.4$
1785 #+END_SRC
1786
1787 As with generating keys manually, to preconfigure expanded preferences
1788 for the cipher, digest and compression algorithms, the =gpg.conf= file
1789 must contain those details in the home directory in which the new key
1790 is being generated.  I used a cut down version of my own =gpg.conf=
1791 file in order to be able to generate this:
1792
1793 #+BEGIN_SRC shell
1794   bash-4.4$ gpg --homedir ~/.gnupg-dm --edit-key 177B7C25DB99745EE2EE13ED026D2F19E99E63AA showpref quit
1795   Secret key is available.
1796
1797   sec  rsa3072/026D2F19E99E63AA
1798        created: 2018-03-15  expires: 2019-03-15  usage: SC
1799        trust: ultimate      validity: ultimate
1800   [ultimate] (1). Danger Mouse <dm@secret.example.net>
1801
1802   [ultimate] (1). Danger Mouse <dm@secret.example.net>
1803        Cipher: TWOFISH, CAMELLIA256, AES256, CAMELLIA192, AES192, CAMELLIA128, AES, BLOWFISH, IDEA, CAST5, 3DES
1804        Digest: SHA512, SHA384, SHA256, SHA224, RIPEMD160, SHA1
1805        Compression: ZLIB, BZIP2, ZIP, Uncompressed
1806        Features: MDC, Keyserver no-modify
1807
1808   bash-4.4$
1809 #+END_SRC
1810
1811
1812 ** Subkeys
1813    :PROPERTIES:
1814    :CUSTOM_ID: keygen-subkeys
1815    :END:
1816
1817 Adding subkeys to a primary key is fairly similar to creating the
1818 primary key with the =create_subkey= method.  Most of the arguments
1819 are the same, but not quite all.  Instead of the =userid= argument
1820 there is now a =key= argument for selecting which primary key to add
1821 the subkey to.
1822
1823 In the following example an encryption subkey will be added to the
1824 primary key.  Since Danger Mouse is a security conscious secret agent,
1825 this subkey will only be valid for about six months, half the length
1826 of the primary key.
1827
1828 #+BEGIN_SRC python -i
1829 import gpg
1830
1831 c = gpg.Context()
1832 c.home_dir = "~/.gnupg-dm"
1833
1834 key = c.get_key(dmkey.fpr, secret=True)
1835 dmsub = c.create_subkey(key, algorithm="rsa3072", expires_in=15768000,
1836                         encrypt=True)
1837 #+END_SRC
1838
1839 As with the primary key, the results here can be checked with:
1840
1841 #+BEGIN_SRC python -i
1842 print("""
1843  Fingerprint:  {0}
1844  Primary Key:  {1}
1845   Public Key:  {2}
1846   Secret Key:  {3}
1847  Sub Key:  {4}
1848 User IDs:  {5}
1849 """.format(dmsub.fpr, dmsub.primary, dmsub.pubkey, dmsub.seckey, dmsub.sub,
1850            dmsub.uid))
1851 #+END_SRC
1852
1853 As well as on the command line with:
1854
1855 #+BEGIN_SRC shell
1856   bash-4.4$ gpg --homedir ~/.gnupg-dm -K
1857   ~/.gnupg-dm/pubring.kbx
1858   ----------------------
1859   sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
1860         177B7C25DB99745EE2EE13ED026D2F19E99E63AA
1861   uid           [ultimate] Danger Mouse <dm@secret.example.net>
1862   ssb   rsa3072 2018-03-15 [E] [expires: 2018-09-13]
1863
1864   bash-4.4$
1865 #+END_SRC
1866
1867
1868 ** User IDs
1869    :PROPERTIES:
1870    :CUSTOM_ID: keygen-uids
1871    :END:
1872
1873
1874 *** Adding User IDs
1875     :PROPERTIES:
1876     :CUSTOM_ID: keygen-uids-add
1877     :END:
1878
1879 By comparison to creating primary keys and subkeys, adding a new user
1880 ID to an existing key is much simpler.  The method used to do this is
1881 =key_add_uid= and the only arguments it takes are for the =key= and
1882 the new =uid=.
1883
1884 #+BEGIN_SRC python -i
1885 import gpg
1886
1887 c = gpg.Context()
1888 c.home_dir = "~/.gnupg-dm"
1889
1890 dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
1891 key = c.get_key(dmfpr, secret=True)
1892 uid = "Danger Mouse <danger.mouse@secret.example.net>"
1893
1894 c.key_add_uid(key, uid)
1895 #+END_SRC
1896
1897 Unsurprisingly the result of this is:
1898
1899 #+BEGIN_SRC shell
1900   bash-4.4$ gpg --homedir ~/.gnupg-dm -K
1901   ~/.gnupg-dm/pubring.kbx
1902   ----------------------
1903   sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
1904         177B7C25DB99745EE2EE13ED026D2F19E99E63AA
1905   uid           [ultimate] Danger Mouse <danger.mouse@secret.example.net>
1906   uid           [ultimate] Danger Mouse <dm@secret.example.net>
1907   ssb   rsa3072 2018-03-15 [E] [expires: 2018-09-13]
1908
1909   bash-4.4$
1910 #+END_SRC
1911
1912
1913 *** Revokinging User IDs
1914     :PROPERTIES:
1915     :CUSTOM_ID: keygen-uids-revoke
1916     :END:
1917
1918 Revoking a user ID is a fairly similar process, except that it uses
1919 the =key_revoke_uid= method.
1920
1921 #+BEGIN_SRC python -i
1922 import gpg
1923
1924 c = gpg.Context()
1925 c.home_dir = "~/.gnupg-dm"
1926
1927 dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
1928 key = c.get_key(dmfpr, secret=True)
1929 uid = "Danger Mouse <danger.mouse@secret.example.net>"
1930
1931 c.key_revoke_uid(key, uid)
1932 #+END_SRC
1933
1934
1935 ** Key certification
1936    :PROPERTIES:
1937    :CUSTOM_ID: key-sign
1938    :END:
1939
1940 Since key certification is more frequently referred to as key signing,
1941 the method used to perform this function is =key_sign=.
1942
1943 The =key_sign= method takes four arguments: =key=, =uids=,
1944 =expires_in= and =local=.  The default value of =uids= is =None= and
1945 which results in all user IDs being selected.  The default value of
1946 both =expires_in= and =local= is =False=; which results in the
1947 signature never expiring and being able to be exported.
1948
1949 The =key= is the key being signed rather than the key doing the
1950 signing.  To change the key doing the signing refer to the signing key
1951 selection above for signing messages and files.
1952
1953 If the =uids= value is not =None= then it must either be a string to
1954 match a single user ID or a list of strings to match multiple user
1955 IDs.  In this case the matching of those strings must be precise and
1956 it is case sensitive.
1957
1958 To sign Danger Mouse's key for just the initial user ID with a
1959 signature which will last a little over a month, do this:
1960
1961 #+BEGIN_SRC python -i
1962 import gpg
1963
1964 c = gpg.Context()
1965 uid = "Danger Mouse <dm@secret.example.net>"
1966
1967 dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
1968 key = c.get_key(dmfpr, secret=True)
1969 c.key_sign(key, uids=uid, expires_in=2764800)
1970 #+END_SRC
1971
1972
1973 * Miscellaneous work-arounds
1974   :PROPERTIES:
1975   :CUSTOM_ID: cheats-and-hacks
1976   :END:
1977
1978
1979 ** Group lines
1980    :PROPERTIES:
1981    :CUSTOM_ID: group-lines
1982    :END:
1983
1984 There is not yet an easy way to access groups configured in the
1985 gpg.conf file from within GPGME.  As a consequence these central
1986 groupings of keys cannot be shared amongst multiple programs, such as
1987 MUAs readily.
1988
1989 The following code, however, provides a work-around for obtaining this
1990 information in Python.
1991
1992 #+BEGIN_SRC python -i
1993 import subprocess
1994 import sys
1995
1996 if sys.platform == "win32":
1997     gpgconfcmd = "gpgconf.exe --list-options gpg"
1998 else:
1999     gpgconfcmd = "gpgconf --list-options gpg"
2000
2001 try:
2002     lines = subprocess.getoutput(gpgconfcmd).splitlines()
2003 except:
2004     process = subprocess.Popen(gpgconfcmd.split(), stdout=subprocess.PIPE)
2005     procom = process.communicate()
2006     if sys.version_info[0] == 2:
2007         lines = procom[0].splitlines()
2008     else:
2009         lines = procom[0].decode().splitlines()
2010
2011 for i in range(len(lines)):
2012     if lines[i].startswith("group") is True:
2013         line = lines[i]
2014     else:
2015         pass
2016
2017 groups = line.split(":")[-1].replace('"', '').split(',')
2018
2019 group_lines = []
2020 group_lists = []
2021
2022 for i in range(len(groups)):
2023     group_lines.append(groups[i].split("="))
2024     group_lists.append(groups[i].split("="))
2025
2026 for i in range(len(group_lists)):
2027     group_lists[i][1] = group_lists[i][1].split()
2028 #+END_SRC
2029
2030 The result of that code is that =group_lines= is a list of lists where
2031 =group_lines[i][0]= is the name of the group and =group_lines[i][1]=
2032 is the key IDs of the group as a string.
2033
2034 The =group_lists= result is very similar in that it is a list of
2035 lists.  The first part, =group_lists[i][0]= matches
2036 =group_lines[i][0]= as the name of the group, but =group_lists[i][1]=
2037 is the key IDs of the group as a string.
2038
2039 A demonstration of using the =groups.py= module is also available in
2040 the form of the executable =mutt-groups.py= script.  This second
2041 script reads all the group entries in a user's =gpg.conf= file and
2042 converts them into crypt-hooks suitable for use with the Mutt and
2043 Neomutt mail clients.
2044
2045
2046 * Copyright, Draft Editions and Licensing
2047   :PROPERTIES:
2048   :CUSTOM_ID: copyright-and-license
2049   :END:
2050
2051
2052 ** Copyright
2053    :PROPERTIES:
2054    :CUSTOM_ID: copyright
2055    :END:
2056
2057 Copyright © The GnuPG Project, 2018.
2058
2059 Copyright (C) The GnuPG Project, 2018.
2060
2061
2062 ** Draft Editions of this HOWTO
2063    :PROPERTIES:
2064    :CUSTOM_ID: draft-editions
2065    :END:
2066
2067 Draft editions of this HOWTO may be periodically available directly
2068 from the author at any of the following URLs:
2069
2070 - [[https://files.au.adversary.org/crypto/gpgme-python-howto.html][GPGME Python Bindings HOWTO draft (XHTML AWS S3 SSL)]]
2071 - [[http://files.au.adversary.org/crypto/gpgme-python-howto.html][GPGME Python Bindings HOWTO draft (XHTML AWS S3 no SSL)]]
2072 - [[https://files.au.adversary.org/crypto/gpgme-python-howto.texi][GPGME Python Bindings HOWTO draft (Texinfo file AWS S3 SSL)]]
2073 - [[http://files.au.adversary.org/crypto/gpgme-python-howto.texi][GPGME Python Bindings HOWTO draft (Texinfo file AWS S3 no SSL)]]
2074 - [[https://files.au.adversary.org/crypto/gpgme-python-howto.info][GPGME Python Bindings HOWTO draft (Info file AWS S3 SSL)]]
2075 - [[http://files.au.adversary.org/crypto/gpgme-python-howto.info][GPGME Python Bindings HOWTO draft (Info file AWS S3 no SSL)]]
2076 - [[https://files.au.adversary.org/crypto/gpgme-python-howto.xml][GPGME Python Bindings HOWTO draft (Docbook 4.2 AWS S3 SSL)]]
2077 - [[http://files.au.adversary.org/crypto/gpgme-python-howto.xml][GPGME Python Bindings HOWTO draft (Docbook 4.2 AWS S3 no SSL)]]
2078
2079 All of these draft versions are generated from this document via Emacs
2080 [[https://orgmode.org/][Org mode]] and [[https://www.gnu.org/software/texinfo/][GNU Texinfo]].
2081
2082 In addition to these there is a significantly less frequently updated
2083 version as a HTML [[https://files.au.adversary.org/crypto/gpgme-python-howto/webhelp/index.html][WebHelp site]] (AWS S3 SSL); generated from DITA XML
2084 source files, which can be found in [[https://dev.gnupg.org/source/gpgme/browse/ben%252Fhowto-dita/][an alternative branch]] of the GPGME
2085 git repository.
2086
2087 These draft editions are not official documents and the version of
2088 documentation in the master branch or which ships with released
2089 versions is the only official documentation.  Nevertheless, these
2090 draft editions may occasionally be of use by providing more accessible
2091 web versions which are updated between releases.  They are provided on
2092 the understanding that they may contain errors or may contain content
2093 subject to change prior to an official release.
2094
2095
2096 ** License GPL compatible
2097    :PROPERTIES:
2098    :CUSTOM_ID: license
2099    :END:
2100
2101 This file is free software; as a special exception the author gives
2102 unlimited permission to copy and/or distribute it, with or without
2103 modifications, as long as this notice is preserved.
2104
2105 This file is distributed in the hope that it will be useful, but
2106 WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
2107 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
2108 PURPOSE.
2109
2110
2111 * Footnotes
2112
2113 [fn:1] =Short_History.org= and/or =Short_History.html=.
2114
2115 [fn:2] The =lang/python/docs/= directory in the GPGME source.
2116
2117 [fn:3] As Python 3.7 is a very recent release, it is not given
2118 priority over 3.6 yet, but will probably be prioritised by the release
2119 of Python 3.7.2.
2120
2121 [fn:4] Yes, even if you use virtualenv with everything you do in
2122 Python.  If you want to install this module as just your user account
2123 then you will need to manually configure, compile and install the
2124 /entire/ GnuPG stack as that user as well.  This includes libraries
2125 which are not often installed that way.  It can be done and there are
2126 circumstances under which it is worthwhile, but generally only on
2127 POSIX systems which utilise single user mode (some even require it).
2128
2129 [fn:5] You probably don't really want to do this.  Searching the
2130 keyservers for "gnupg.org" produces over 400 results, the majority of
2131 which aren't actually at the gnupg.org domain, but just included a
2132 comment regarding the project in their key somewhere.