docs: python howto texinfo update
[gpgme.git] / lang / python / docs / GPGMEpythonHOWTOen.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:         | 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 *** I don't like SWIG, Use CFFI instead
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
442 * Fundamentals
443   :PROPERTIES:
444   :CUSTOM_ID: howto-fund-a-mental
445   :END:
446
447 Before we can get to the fun stuff, there are a few matters regarding
448 GPGME's design which hold true whether you're dealing with the C code
449 directly or these Python bindings.
450
451
452 ** No REST
453    :PROPERTIES:
454    :CUSTOM_ID: no-rest-for-the-wicked
455    :END:
456
457 The first part of which is or will be fairly blatantly obvious upon
458 viewing the first example, but it's worth reiterating anyway.  That
459 being that this API is /*not*/ a REST API.  Nor indeed could it ever
460 be one.
461
462 Most, if not all, Python programmers (and not just Python programmers)
463 know how easy it is to work with a RESTful API.  In fact they've
464 become so popular that many other APIs attempt to emulate REST-like
465 behaviour as much as they are able.  Right down to the use of JSON
466 formatted output to facilitate the use of their API without having to
467 retrain developers.
468
469 This API does not do that.  It would not be able to do that and also
470 provide access to the entire C API on which it's built.  It does,
471 however, provide a very pythonic interface on top of the direct
472 bindings and it's this pythonic layer that this HOWTO deals with.
473
474
475 ** Context
476    :PROPERTIES:
477    :CUSTOM_ID: howto-get-context
478    :END:
479
480 One of the reasons which prevents this API from being RESTful is that
481 most operations require more than one instruction to the API to
482 perform the task.  Sure, there are certain functions which can be
483 performed simultaneously, particularly if the result known or strongly
484 anticipated (e.g. selecting and encrypting to a key known to be in the
485 public keybox).
486
487 There are many more, however, which cannot be manipulated so readily:
488 they must be performed in a specific sequence and the result of one
489 operation has a direct bearing on the outcome of subsequent
490 operations.  Not merely by generating an error either.
491
492 When dealing with this type of persistent state on the web, full of
493 both the RESTful and REST-like, it's most commonly referred to as a
494 session.  In GPGME, however, it is called a context and every
495 operation type has one.
496
497
498 * Working with keys
499   :PROPERTIES:
500   :CUSTOM_ID: howto-keys
501   :END:
502
503
504 ** Key selection
505    :PROPERTIES:
506    :CUSTOM_ID: howto-keys-selection
507    :END:
508
509 Selecting keys to encrypt to or to sign with will be a common
510 occurrence when working with GPGMe and the means available for doing
511 so are quite simple.
512
513 They do depend on utilising a Context; however once the data is
514 recorded in another variable, that Context does not need to be the
515 same one which subsequent operations are performed.
516
517 The easiest way to select a specific key is by searching for that
518 key's key ID or fingerprint, preferably the full fingerprint without
519 any spaces in it.  A long key ID will probably be okay, but is not
520 advised and short key IDs are already a problem with some being
521 generated to match specific patterns.  It does not matter whether the
522 pattern is upper or lower case.
523
524 So this is the best method:
525
526 #+BEGIN_SRC python -i
527 import gpg
528
529 k = gpg.Context().keylist(pattern="258E88DCBD3CD44D8E7AB43F6ECB6AF0DEADBEEF")
530 keys = list(k)
531 #+END_SRC
532
533 This is passable and very likely to be common:
534
535 #+BEGIN_SRC python -i
536 import gpg
537
538 k = gpg.Context().keylist(pattern="0x6ECB6AF0DEADBEEF")
539 keys = list(k)
540 #+END_SRC
541
542 And this is a really bad idea:
543
544 #+BEGIN_SRC python -i
545 import gpg
546
547 k = gpg.Context().keylist(pattern="0xDEADBEEF")
548 keys = list(k)
549 #+END_SRC
550
551 Alternatively it may be that the intention is to create a list of keys
552 which all match a particular search string.  For instance all the
553 addresses at a particular domain, like this:
554
555 #+BEGIN_SRC python -i
556 import gpg
557
558 ncsc = gpg.Context().keylist(pattern="ncsc.mil")
559 nsa = list(ncsc)
560 #+END_SRC
561
562
563 *** Counting keys
564     :PROPERTIES:
565     :CUSTOM_ID: howto-keys-counting
566     :END:
567
568 Counting the number of keys in your public keybox (=pubring.kbx=), the
569 format which has superseded the old keyring format (=pubring.gpg= and
570 =secring.gpg=), or the number of secret keys is a very simple task.
571
572 #+BEGIN_SRC python -i
573 import gpg
574
575 c = gpg.Context()
576 seckeys = c.keylist(pattern=None, secret=True)
577 pubkeys = c.keylist(pattern=None, secret=False)
578
579 seclist = list(seckeys)
580 secnum = len(seclist)
581
582 publist = list(pubkeys)
583 pubnum = len(publist)
584
585 print("""
586   Number of secret keys:  {0}
587   Number of public keys:  {1}
588 """.format(secnum, pubnum))
589 #+END_SRC
590
591
592 ** Get key
593    :PROPERTIES:
594    :CUSTOM_ID: howto-get-key
595    :END:
596
597 An alternative method of getting a single key via its fingerprint is
598 available directly within a Context with =Context().get_key=.  This is
599 the preferred method of selecting a key in order to modify it, sign or
600 certify it and for obtaining relevant data about a single key as a
601 part of other functions; when verifying a signature made by that key,
602 for instance.
603
604 By default this method will select public keys, but it can select
605 secret keys as well.
606
607 This first example demonstrates selecting the current key of Werner
608 Koch, which is due to expire at the end of 2018:
609
610 #+BEGIN_SRC python -i
611 import gpg
612
613 fingerprint = "80615870F5BAD690333686D0F2AD85AC1E42B367"
614 key = gpg.Context().get_key(fingerprint)
615 #+END_SRC
616
617 Whereas this example demonstrates selecting the author's current key
618 with the =secret= key word argument set to =True=:
619
620 #+BEGIN_SRC python -i
621 import gpg
622
623 fingerprint = "DB4724E6FA4286C92B4E55C4321E4E2373590E5D"
624 key = gpg.Context().get_key(fingerprint, secret=True)
625 #+END_SRC
626
627 It is, of course, quite possible to select expired, disabled and
628 revoked keys with this function, but only to effectively display
629 information about those keys.
630
631 It is also possible to use both unicode or string literals and byte
632 literals with the fingerprint when getting a key in this way.
633
634
635 ** Importing keys
636    :PROPERTIES:
637    :CUSTOM_ID: howto-import-key
638    :END:
639
640 Importing keys is possible with the =key_import()= method and takes
641 one argument which is a bytes literal object containing either the
642 binary or ASCII armoured key data for one or more keys.
643
644 The following example retrieves one or more keys from the SKS
645 keyservers via the web using the requests module. Since requests
646 returns the content as a bytes literal object, we can then use that
647 directly to import the resulting data into our keybox.
648
649 #+BEGIN_SRC python -i
650 import gpg
651 import os.path
652 import requests
653
654 c = gpg.Context()
655 url = "https://sks-keyservers.net/pks/lookup"
656 pattern = input("Enter the pattern to search for key or user IDs: ")
657 payload = { "op": "get", "search": pattern }
658
659 r = requests.get(url, verify=True, params=payload)
660 result = c.key_import(r.content)
661
662 if result is not None and hasattr(result, "considered") is False:
663     print(result)
664 elif result is not None and hasattr(result, "considered") is True:
665     num_keys = len(result.imports)
666     new_revs = result.new_revocations
667     new_sigs = result.new_signatures
668     new_subs = result.new_sub_keys
669     new_uids = result.new_user_ids
670     new_scrt = result.secret_imported
671     nochange = result.unchanged
672     print("""
673   The total number of keys considered for import was:  {0}
674
675      Number of keys revoked:  {1}
676    Number of new signatures:  {2}
677       Number of new subkeys:  {3}
678      Number of new user IDs:  {4}
679   Number of new secret keys:  {5}
680    Number of unchanged keys:  {6}
681
682   The key IDs for all considered keys were:
683 """.format(num_keys, new_revs, new_sigs, new_subs, new_uids, new_scrt,
684            nochange))
685     for i in range(num_keys):
686         print("{0}\n".format(result.imports[i].fpr))
687 else:
688     pass
689 #+END_SRC
690
691 *NOTE:* When searching for a key ID of any length or a fingerprint
692 (without spaces), the SKS servers require the the leading =0x=
693 indicative of hexadecimal be included. Also note that the old short
694 key IDs (e.g. =0xDEADBEEF=) should no longer be used due to the
695 relative ease by which such key IDs can be reproduced, as demonstrated
696 by the Evil32 Project in 2014 (which was subsequently exploited in
697 2016).
698
699 Here is a variation on the above which checks the constrained
700 ProtonMail keyserver for ProtonMail public keys.
701
702 #+BEGIN_SRC python -i
703 import gpg
704 import requests
705 import sys
706
707 print("""
708 This script searches the ProtonMail key server for the specified key and
709 imports it.
710 """)
711
712 c = gpg.Context(armor=True)
713 url = "https://api.protonmail.ch/pks/lookup"
714 ksearch = []
715
716 if len(sys.argv) >= 2:
717     keyterm = sys.argv[1]
718 else:
719     keyterm = input("Enter the key ID, UID or search string: ")
720
721 if keyterm.count("@") == 2 and keyterm.startswith("@") is True:
722     ksearch.append(keyterm[1:])
723     ksearch.append(keyterm[1:])
724     ksearch.append(keyterm[1:])
725 elif keyterm.count("@") == 1 and keyterm.startswith("@") is True:
726     ksearch.append("{0}@protonmail.com".format(keyterm[1:]))
727     ksearch.append("{0}@protonmail.ch".format(keyterm[1:]))
728     ksearch.append("{0}@pm.me".format(keyterm[1:]))
729 elif keyterm.count("@") == 0:
730     ksearch.append("{0}@protonmail.com".format(keyterm))
731     ksearch.append("{0}@protonmail.ch".format(keyterm))
732     ksearch.append("{0}@pm.me".format(keyterm))
733 elif keyterm.count("@") == 2 and keyterm.startswith("@") is False:
734     uidlist = keyterm.split("@")
735     for uid in uidlist:
736         ksearch.append("{0}@protonmail.com".format(uid))
737         ksearch.append("{0}@protonmail.ch".format(uid))
738         ksearch.append("{0}@pm.me".format(uid))
739 elif keyterm.count("@") > 2:
740     uidlist = keyterm.split("@")
741     for uid in uidlist:
742         ksearch.append("{0}@protonmail.com".format(uid))
743         ksearch.append("{0}@protonmail.ch".format(uid))
744         ksearch.append("{0}@pm.me".format(uid))
745 else:
746     ksearch.append(keyterm)
747
748 for k in ksearch:
749     payload = {"op": "get", "search": k}
750     try:
751         r = requests.get(url, verify=True, params=payload)
752         if r.ok is True:
753             result = c.key_import(r.content)
754         elif r.ok is False:
755             result = r.content
756     except Exception as e:
757         result = None
758
759     if result is not None and hasattr(result, "considered") is False:
760         print("{0} for {1}".format(result.decode(), k))
761     elif result is not None and hasattr(result, "considered") is True:
762         num_keys = len(result.imports)
763         new_revs = result.new_revocations
764         new_sigs = result.new_signatures
765         new_subs = result.new_sub_keys
766         new_uids = result.new_user_ids
767         new_scrt = result.secret_imported
768         nochange = result.unchanged
769         print("""
770 The total number of keys considered for import was:  {0}
771
772 With UIDs wholely or partially matching the following string:
773
774         {1}
775
776    Number of keys revoked:  {2}
777  Number of new signatures:  {3}
778     Number of new subkeys:  {4}
779    Number of new user IDs:  {5}
780 Number of new secret keys:  {6}
781  Number of unchanged keys:  {7}
782
783 The key IDs for all considered keys were:
784 """.format(num_keys, k, new_revs, new_sigs, new_subs, new_uids, new_scrt,
785            nochange))
786         for i in range(num_keys):
787             print(result.imports[i].fpr)
788         print("")
789     elif result is None:
790         print(e)
791 #+END_SRC
792
793 Both the above example, [[../examples/howto/pmkey-import.py][pmkey-import.py]], and a version which prompts
794 for an alternative GnuPG home directory, [[../examples/howto/pmkey-import-alt.py][pmkey-import-alt.py]], are
795 available with the other examples and are executable scripts.
796
797 Note that while the ProtonMail servers are based on the SKS servers,
798 their server is related more to their API and is not feature complete
799 by comparison to the servers in the SKS pool.  One notable difference
800 being that the ProtonMail server does not permit non ProtonMail users
801 to update their own keys, which could be a vector for attacking
802 ProtonMail users who may not receive a key's revocation if it had been
803 compromised.
804
805
806 ** Exporting keys
807    :PROPERTIES:
808    :CUSTOM_ID: howto-export-key
809    :END:
810
811 Exporting keys remains a reasonably simple task, but has been
812 separated into three different functions for the OpenPGP cryptographic
813 engine.  Two of those functions are for exporting public keys and the
814 third is for exporting secret keys.
815
816
817 *** Exporting public keys
818     :PROPERTIES:
819     :CUSTOM_ID: howto-export-public-key
820     :END:
821
822 There are two methods of exporting public keys, both of which are very
823 similar to the other.  The default method, =key_export()=, will export
824 a public key or keys matching a specified pattern as normal.  The
825 alternative, the =key_export_minimal()= method, will do the same thing
826 except producing a minimised output with extra signatures and third
827 party signatures or certifications removed.
828
829 #+BEGIN_SRC python -i
830 import gpg
831 import os.path
832 import sys
833
834 print("""
835 This script exports one or more public keys.
836 """)
837
838 c = gpg.Context(armor=True)
839
840 if len(sys.argv) >= 4:
841     keyfile = sys.argv[1]
842     logrus = sys.argv[2]
843     homedir = sys.argv[3]
844 elif len(sys.argv) == 3:
845     keyfile = sys.argv[1]
846     logrus = sys.argv[2]
847     homedir = input("Enter the GPG configuration directory path (optional): ")
848 elif len(sys.argv) == 2:
849     keyfile = sys.argv[1]
850     logrus = input("Enter the UID matching the key(s) to export: ")
851     homedir = input("Enter the GPG configuration directory path (optional): ")
852 else:
853     keyfile = input("Enter the path and filename to save the secret key to: ")
854     logrus = input("Enter the UID matching the key(s) to export: ")
855     homedir = input("Enter the GPG configuration directory path (optional): ")
856
857 if homedir.startswith("~"):
858     if os.path.exists(os.path.expanduser(homedir)) is True:
859         c.home_dir = os.path.expanduser(homedir)
860     else:
861         pass
862 elif os.path.exists(homedir) is True:
863     c.home_dir = homedir
864 else:
865     pass
866
867 try:
868     result = c.key_export(pattern=logrus)
869 except:
870     result = c.key_export(pattern=None)
871
872 if result is not None:
873     with open(keyfile, "wb") as f:
874         f.write(result)
875 else:
876     pass
877 #+END_SRC
878
879 It is important to note that the result will only return =None= when a
880 pattern has been entered for =logrus=, but it has not matched any
881 keys. When the search pattern itself is set to =None= this triggers
882 the exporting of the entire public keybox.
883
884 #+BEGIN_SRC python -i
885 import gpg
886 import os.path
887 import sys
888
889 print("""
890 This script exports one or more public keys in minimised form.
891 """)
892
893 c = gpg.Context(armor=True)
894
895 if len(sys.argv) >= 4:
896     keyfile = sys.argv[1]
897     logrus = sys.argv[2]
898     homedir = sys.argv[3]
899 elif len(sys.argv) == 3:
900     keyfile = sys.argv[1]
901     logrus = sys.argv[2]
902     homedir = input("Enter the GPG configuration directory path (optional): ")
903 elif len(sys.argv) == 2:
904     keyfile = sys.argv[1]
905     logrus = input("Enter the UID matching the key(s) to export: ")
906     homedir = input("Enter the GPG configuration directory path (optional): ")
907 else:
908     keyfile = input("Enter the path and filename to save the secret key to: ")
909     logrus = input("Enter the UID matching the key(s) to export: ")
910     homedir = input("Enter the GPG configuration directory path (optional): ")
911
912 if homedir.startswith("~"):
913     if os.path.exists(os.path.expanduser(homedir)) is True:
914         c.home_dir = os.path.expanduser(homedir)
915     else:
916         pass
917 elif os.path.exists(homedir) is True:
918     c.home_dir = homedir
919 else:
920     pass
921
922 try:
923     result = c.key_export_minimal(pattern=logrus)
924 except:
925     result = c.key_export_minimal(pattern=None)
926
927 if result is not None:
928     with open(keyfile, "wb") as f:
929         f.write(result)
930 else:
931     pass
932 #+END_SRC
933
934
935 *** Exporting secret keys
936     :PROPERTIES:
937     :CUSTOM_ID: howto-export-secret-key
938     :END:
939
940 Exporting secret keys is, functionally, very similar to exporting
941 public keys; save for the invocation of =pinentry= via =gpg-agent= in
942 order to securely enter the key's passphrase and authorise the export.
943
944 The following example exports the secret key to a file which is then
945 set with the same permissions as the output files created by the
946 command line secret key export options.
947
948 #+BEGIN_SRC python -i
949 import gpg
950 import os
951 import os.path
952 import sys
953
954 print("""
955 This script exports one or more secret keys.
956
957 The gpg-agent and pinentry are invoked to authorise the export.
958 """)
959
960 c = gpg.Context(armor=True)
961
962 if len(sys.argv) >= 4:
963     keyfile = sys.argv[1]
964     logrus = sys.argv[2]
965     homedir = sys.argv[3]
966 elif len(sys.argv) == 3:
967     keyfile = sys.argv[1]
968     logrus = sys.argv[2]
969     homedir = input("Enter the GPG configuration directory path (optional): ")
970 elif len(sys.argv) == 2:
971     keyfile = sys.argv[1]
972     logrus = input("Enter the UID matching the secret key(s) to export: ")
973     homedir = input("Enter the GPG configuration directory path (optional): ")
974 else:
975     keyfile = input("Enter the path and filename to save the secret key to: ")
976     logrus = input("Enter the UID matching the secret key(s) to export: ")
977     homedir = input("Enter the GPG configuration directory path (optional): ")
978
979 if homedir.startswith("~"):
980     if os.path.exists(os.path.expanduser(homedir)) is True:
981         c.home_dir = os.path.expanduser(homedir)
982     else:
983         pass
984 elif os.path.exists(homedir) is True:
985     c.home_dir = homedir
986 else:
987     pass
988
989 try:
990     result = c.key_export_secret(pattern=logrus)
991 except:
992     result = c.key_export_secret(pattern=None)
993
994 if result is not None:
995     with open(keyfile, "wb") as f:
996         f.write(result)
997     os.chmod(keyfile, 0o600)
998 else:
999     pass
1000 #+END_SRC
1001
1002 Alternatively the approach of the following script can be used.  This
1003 longer example saves the exported secret key(s) in files in the GnuPG
1004 home directory, in addition to setting the file permissions as only
1005 readable and writable by the user.  It also exports the secret key(s)
1006 twice in order to output both GPG binary (=.gpg=) and ASCII armoured
1007 (=.asc=) files.
1008
1009 #+BEGIN_SRC python -i
1010 import gpg
1011 import os
1012 import os.path
1013 import subprocess
1014 import sys
1015
1016 print("""
1017 This script exports one or more secret keys as both ASCII armored and binary
1018 file formats, saved in files within the user's GPG home directory.
1019
1020 The gpg-agent and pinentry are invoked to authorise the export.
1021 """)
1022
1023 if sys.platform == "win32":
1024     gpgconfcmd = "gpgconf.exe --list-dirs homedir"
1025 else:
1026     gpgconfcmd = "gpgconf --list-dirs homedir"
1027
1028 a = gpg.Context(armor=True)
1029 b = gpg.Context()
1030 c = gpg.Context()
1031
1032 if len(sys.argv) >= 4:
1033     keyfile = sys.argv[1]
1034     logrus = sys.argv[2]
1035     homedir = sys.argv[3]
1036 elif len(sys.argv) == 3:
1037     keyfile = sys.argv[1]
1038     logrus = sys.argv[2]
1039     homedir = input("Enter the GPG configuration directory path (optional): ")
1040 elif len(sys.argv) == 2:
1041     keyfile = sys.argv[1]
1042     logrus = input("Enter the UID matching the secret key(s) to export: ")
1043     homedir = input("Enter the GPG configuration directory path (optional): ")
1044 else:
1045     keyfile = input("Enter the filename to save the secret key to: ")
1046     logrus = input("Enter the UID matching the secret key(s) to export: ")
1047     homedir = input("Enter the GPG configuration directory path (optional): ")
1048
1049 if homedir.startswith("~"):
1050     if os.path.exists(os.path.expanduser(homedir)) is True:
1051         c.home_dir = os.path.expanduser(homedir)
1052     else:
1053         pass
1054 elif os.path.exists(homedir) is True:
1055     c.home_dir = homedir
1056 else:
1057     pass
1058
1059 if c.home_dir is not None:
1060     if c.home_dir.endswith("/"):
1061         gpgfile = "{0}{1}.gpg".format(c.home_dir, keyfile)
1062         ascfile = "{0}{1}.asc".format(c.home_dir, keyfile)
1063     else:
1064         gpgfile = "{0}/{1}.gpg".format(c.home_dir, keyfile)
1065         ascfile = "{0}/{1}.asc".format(c.home_dir, keyfile)
1066 else:
1067     if os.path.exists(os.environ["GNUPGHOME"]) is True:
1068         hd = os.environ["GNUPGHOME"]
1069     else:
1070         try:
1071             hd = subprocess.getoutput(gpgconfcmd)
1072         except:
1073             process = subprocess.Popen(gpgconfcmd.split(),
1074                                        stdout=subprocess.PIPE)
1075             procom = process.communicate()
1076             if sys.version_info[0] == 2:
1077                 hd = procom[0].strip()
1078             else:
1079                 hd = procom[0].decode().strip()
1080     gpgfile = "{0}/{1}.gpg".format(hd, keyfile)
1081     ascfile = "{0}/{1}.asc".format(hd, keyfile)
1082
1083 try:
1084     a_result = a.key_export_secret(pattern=logrus)
1085     b_result = b.key_export_secret(pattern=logrus)
1086 except:
1087     a_result = a.key_export_secret(pattern=None)
1088     b_result = b.key_export_secret(pattern=None)
1089
1090 if a_result is not None:
1091     with open(ascfile, "wb") as f:
1092         f.write(a_result)
1093     os.chmod(ascfile, 0o600)
1094 else:
1095     pass
1096
1097 if b_result is not None:
1098     with open(gpgfile, "wb") as f:
1099         f.write(b_result)
1100     os.chmod(gpgfile, 0o600)
1101 else:
1102     pass
1103 #+END_SRC
1104
1105
1106 * Basic Functions
1107   :PROPERTIES:
1108   :CUSTOM_ID: howto-the-basics
1109   :END:
1110
1111 The most frequently called features of any cryptographic library will
1112 be the most fundamental tasks for encryption software.  In this
1113 section we will look at how to programmatically encrypt data, decrypt
1114 it, sign it and verify signatures.
1115
1116
1117 ** Encryption
1118    :PROPERTIES:
1119    :CUSTOM_ID: howto-basic-encryption
1120    :END:
1121
1122 Encrypting is very straight forward.  In the first example below the
1123 message, =text=, is encrypted to a single recipient's key.  In the
1124 second example the message will be encrypted to multiple recipients.
1125
1126
1127 *** Encrypting to one key
1128     :PROPERTIES:
1129     :CUSTOM_ID: howto-basic-encryption-single
1130     :END:
1131
1132 Once the the Context is set the main issues with encrypting data is
1133 essentially reduced to key selection and the keyword arguments
1134 specified in the =gpg.Context().encrypt()= method.
1135
1136 Those keyword arguments are: =recipients=, a list of keys encrypted to
1137 (covered in greater detail in the following section); =sign=, whether
1138 or not to sign the plaintext data, see subsequent sections on signing
1139 and verifying signatures below (defaults to =True=); =sink=, to write
1140 results or partial results to a secure sink instead of returning it
1141 (defaults to =None=); =passphrase=, only used when utilising symmetric
1142 encryption (defaults to =None=); =always_trust=, used to override the
1143 trust model settings for recipient keys (defaults to =False=);
1144 =add_encrypt_to=, utilises any preconfigured =encrypt-to= or
1145 =default-key= settings in the user's =gpg.conf= file (defaults to
1146 =False=); =prepare=, prepare for encryption (defaults to =False=);
1147 =expect_sign=, prepare for signing (defaults to =False=); =compress=,
1148 compresses the plaintext prior to encryption (defaults to =True=).
1149
1150 #+BEGIN_SRC python -i
1151 import gpg
1152
1153 a_key = "0x12345678DEADBEEF"
1154 text = b"""Some text to test with.
1155
1156 Since the text in this case must be bytes, it is most likely that
1157 the input form will be a separate file which is opened with "rb"
1158 as this is the simplest method of obtaining the correct data format.
1159 """
1160
1161 c = gpg.Context(armor=True)
1162 rkey = list(c.keylist(pattern=a_key, secret=False))
1163 ciphertext, result, sign_result = c.encrypt(text, recipients=rkey, sign=False)
1164
1165 with open("secret_plans.txt.asc", "wb") as afile:
1166     afile.write(ciphertext)
1167 #+END_SRC
1168
1169 Though this is even more likely to be used like this; with the
1170 plaintext input read from a file, the recipient keys used for
1171 encryption regardless of key trust status and the encrypted output
1172 also encrypted to any preconfigured keys set in the =gpg.conf= file:
1173
1174 #+BEGIN_SRC python -i
1175 import gpg
1176
1177 a_key = "0x12345678DEADBEEF"
1178
1179 with open("secret_plans.txt", "rb") as afile:
1180     text = afile.read()
1181
1182 c = gpg.Context(armor=True)
1183 rkey = list(c.keylist(pattern=a_key, secret=False))
1184 ciphertext, result, sign_result = c.encrypt(text, recipients=rkey, sign=True,
1185                                             always_trust=True,
1186                                             add_encrypt_to=True)
1187
1188 with open("secret_plans.txt.asc", "wb") as afile:
1189     afile.write(ciphertext)
1190 #+END_SRC
1191
1192 If the =recipients= paramater is empty then the plaintext is encrypted
1193 symmetrically.  If no =passphrase= is supplied as a parameter or via a
1194 callback registered with the =Context()= then an out-of-band prompt
1195 for the passphrase via pinentry will be invoked.
1196
1197
1198 *** Encrypting to multiple keys
1199     :PROPERTIES:
1200     :CUSTOM_ID: howto-basic-encryption-multiple
1201     :END:
1202
1203 Encrypting to multiple keys essentially just expands upon the key
1204 selection process and the recipients from the previous examples.
1205
1206 The following example encrypts a message (=text=) to everyone with an
1207 email address on the =gnupg.org= domain,[fn:5] but does /not/ encrypt
1208 to a default key or other key which is configured to normally encrypt
1209 to.
1210
1211 #+BEGIN_SRC python -i
1212 import gpg
1213
1214 text = b"""Oh look, another test message.
1215
1216 The same rules apply as with the previous example and more likely
1217 than not, the message will actually be drawn from reading the
1218 contents of a file or, maybe, from entering data at an input()
1219 prompt.
1220
1221 Since the text in this case must be bytes, it is most likely that
1222 the input form will be a separate file which is opened with "rb"
1223 as this is the simplest method of obtaining the correct data
1224 format.
1225 """
1226
1227 c = gpg.Context(armor=True)
1228 rpattern = list(c.keylist(pattern="@gnupg.org", secret=False))
1229 logrus = []
1230
1231 for i in range(len(rpattern)):
1232     if rpattern[i].can_encrypt == 1:
1233         logrus.append(rpattern[i])
1234
1235 ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
1236                                             sign=False, always_trust=True)
1237
1238 with open("secret_plans.txt.asc", "wb") as afile:
1239     afile.write(ciphertext)
1240 #+END_SRC
1241
1242 All it would take to change the above example to sign the message
1243 and also encrypt the message to any configured default keys would
1244 be to change the =c.encrypt= line to this:
1245
1246 #+BEGIN_SRC python -i
1247 ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
1248                                             always_trust=True,
1249                                             add_encrypt_to=True)
1250 #+END_SRC
1251
1252 The only keyword arguments requiring modification are those for which
1253 the default values are changing.  The default value of =sign= is
1254 =True=, the default of =always_trust= is =False=, the default of
1255 =add_encrypt_to= is =False=.
1256
1257 If =always_trust= is not set to =True= and any of the recipient keys
1258 are not trusted (e.g. not signed or locally signed) then the
1259 encryption will raise an error.  It is possible to mitigate this
1260 somewhat with something more like this:
1261
1262 #+BEGIN_SRC python -i
1263 import gpg
1264
1265 with open("secret_plans.txt.asc", "rb") as afile:
1266     text = afile.read()
1267
1268 c = gpg.Context(armor=True)
1269 rpattern = list(c.keylist(pattern="@gnupg.org", secret=False))
1270 logrus = []
1271
1272 for i in range(len(rpattern)):
1273     if rpattern[i].can_encrypt == 1:
1274         logrus.append(rpattern[i])
1275
1276     try:
1277         ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
1278                                                     add_encrypt_to=True)
1279     except gpg.errors.InvalidRecipients as e:
1280         for i in range(len(e.recipients)):
1281             for n in range(len(logrus)):
1282                 if logrus[n].fpr == e.recipients[i].fpr:
1283                     logrus.remove(logrus[n])
1284                 else:
1285                     pass
1286         try:
1287             ciphertext, result, sign_result = c.encrypt(text,
1288                                                         recipients=logrus,
1289                                                         add_encrypt_to=True)
1290             with open("secret_plans.txt.asc", "wb") as afile:
1291                 afile.write(ciphertext)
1292         except:
1293             pass
1294 #+END_SRC
1295
1296 This will attempt to encrypt to all the keys searched for, then remove
1297 invalid recipients if it fails and try again.
1298
1299
1300 ** Decryption
1301    :PROPERTIES:
1302    :CUSTOM_ID: howto-basic-decryption
1303    :END:
1304
1305 Decrypting something encrypted to a key in one's secret keyring is
1306 fairly straight forward.
1307
1308 In this example code, however, preconfiguring either =gpg.Context()=
1309 or =gpg.core.Context()= as =c= is unnecessary because there is no need
1310 to modify the Context prior to conducting the decryption and since the
1311 Context is only used once, setting it to =c= simply adds lines for no
1312 gain.
1313
1314 #+BEGIN_SRC python -i
1315 import gpg
1316
1317 ciphertext = input("Enter path and filename of encrypted file: ")
1318 newfile = input("Enter path and filename of file to save decrypted data to: ")
1319
1320 with open(ciphertext, "rb") as cfile:
1321     try:
1322         plaintext, result, verify_result = gpg.Context().decrypt(cfile)
1323     except gpg.errors.GPGMEError as e:
1324         plaintext = None
1325         print(e)
1326
1327 if plaintext is not None:
1328     with open(newfile, "wb") as nfile:
1329             nfile.write(plaintext)
1330     else:
1331         pass
1332 #+END_SRC
1333
1334 The data available in =plaintext= in this example is the decrypted
1335 content as a byte object, the recipient key IDs and algorithms in
1336 =result= and the results of verifying any signatures of the data in
1337 =verify_result=.
1338
1339
1340 ** Signing text and files
1341    :PROPERTIES:
1342    :CUSTOM_ID: howto-basic-signing
1343    :END:
1344
1345 The following sections demonstrate how to specify keys to sign with.
1346
1347
1348 *** Signing key selection
1349     :PROPERTIES:
1350     :CUSTOM_ID: howto-basic-signing-signers
1351     :END:
1352
1353 By default GPGME and the Python bindings will use the default key
1354 configured for the user invoking the GPGME API.  If there is no
1355 default key specified and there is more than one secret key available
1356 it may be necessary to specify the key or keys with which to sign
1357 messages and files.
1358
1359 #+BEGIN_SRC python -i
1360 import gpg
1361
1362 logrus = input("Enter the email address or string to match signing keys to: ")
1363 hancock = gpg.Context().keylist(pattern=logrus, secret=True)
1364 sig_src = list(hancock)
1365 #+END_SRC
1366
1367 The signing examples in the following sections include the explicitly
1368 designated =signers= parameter in two of the five examples; once where
1369 the resulting signature would be ASCII armoured and once where it
1370 would not be armoured.
1371
1372 While it would be possible to enter a key ID or fingerprint here to
1373 match a specific key, it is not possible to enter two fingerprints and
1374 match two keys since the patten expects a string, bytes or None and
1375 not a list.  A string with two fingerprints won't match any single
1376 key.
1377
1378
1379 *** Normal or default signing messages or files
1380     :PROPERTIES:
1381     :CUSTOM_ID: howto-basic-signing-normal
1382     :END:
1383
1384 The normal or default signing process is essentially the same as is
1385 most often invoked when also encrypting a message or file.  So when
1386 the encryption component is not utilised, the result is to produce an
1387 encoded and signed output which may or may not be ASCII armoured and
1388 which may or may not also be compressed.
1389
1390 By default compression will be used unless GnuPG detects that the
1391 plaintext is already compressed.  ASCII armouring will be determined
1392 according to the value of =gpg.Context().armor=.
1393
1394 The compression algorithm is selected in much the same way as the
1395 symmetric encryption algorithm or the hash digest algorithm is when
1396 multiple keys are involved; from the preferences saved into the key
1397 itself or by comparison with the preferences with all other keys
1398 involved.
1399
1400 #+BEGIN_SRC python -i
1401 import gpg
1402
1403 text0 = """Declaration of ... something.
1404
1405 """
1406 text = text0.encode()
1407
1408 c = gpg.Context(armor=True, signers=sig_src)
1409 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.NORMAL)
1410
1411 with open("/path/to/statement.txt.asc", "w") as afile:
1412     afile.write(signed_data.decode())
1413 #+END_SRC
1414
1415 Though everything in this example is accurate, it is more likely that
1416 reading the input data from another file and writing the result to a
1417 new file will be performed more like the way it is done in the next
1418 example.  Even if the output format is ASCII armoured.
1419
1420 #+BEGIN_SRC python -i
1421 import gpg
1422
1423 with open("/path/to/statement.txt", "rb") as tfile:
1424     text = tfile.read()
1425
1426 c = gpg.Context()
1427 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.NORMAL)
1428
1429 with open("/path/to/statement.txt.sig", "wb") as afile:
1430     afile.write(signed_data)
1431 #+END_SRC
1432
1433
1434 *** Detached signing messages and files
1435     :PROPERTIES:
1436     :CUSTOM_ID: howto-basic-signing-detached
1437     :END:
1438
1439 Detached signatures will often be needed in programmatic uses of
1440 GPGME, either for signing files (e.g. tarballs of code releases) or as
1441 a component of message signing (e.g. PGP/MIME encoded email).
1442
1443 #+BEGIN_SRC python -i
1444 import gpg
1445
1446 text0 = """Declaration of ... something.
1447
1448 """
1449 text = text0.encode()
1450
1451 c = gpg.Context(armor=True)
1452 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.DETACH)
1453
1454 with open("/path/to/statement.txt.asc", "w") as afile:
1455     afile.write(signed_data.decode())
1456 #+END_SRC
1457
1458 As with normal signatures, detached signatures are best handled as
1459 byte literals, even when the output is ASCII armoured.
1460
1461 #+BEGIN_SRC python -i
1462 import gpg
1463
1464 with open("/path/to/statement.txt", "rb") as tfile:
1465     text = tfile.read()
1466
1467 c = gpg.Context(signers=sig_src)
1468 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.DETACH)
1469
1470 with open("/path/to/statement.txt.sig", "wb") as afile:
1471     afile.write(signed_data)
1472 #+END_SRC
1473
1474
1475 *** Clearsigning messages or text
1476     :PROPERTIES:
1477     :CUSTOM_ID: howto-basic-signing-clear
1478     :END:
1479
1480 Though PGP/in-line messages are no longer encouraged in favour of
1481 PGP/MIME, there is still sometimes value in utilising in-line
1482 signatures.  This is where clear-signed messages or text is of value.
1483
1484 #+BEGIN_SRC python -i
1485 import gpg
1486
1487 text0 = """Declaration of ... something.
1488
1489 """
1490 text = text0.encode()
1491
1492 c = gpg.Context()
1493 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.CLEAR)
1494
1495 with open("/path/to/statement.txt.asc", "w") as afile:
1496     afile.write(signed_data.decode())
1497 #+END_SRC
1498
1499 In spite of the appearance of a clear-signed message, the data handled
1500 by GPGME in signing it must still be byte literals.
1501
1502 #+BEGIN_SRC python -i
1503 import gpg
1504
1505 with open("/path/to/statement.txt", "rb") as tfile:
1506     text = tfile.read()
1507
1508 c = gpg.Context()
1509 signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.CLEAR)
1510
1511 with open("/path/to/statement.txt.asc", "wb") as afile:
1512     afile.write(signed_data)
1513 #+END_SRC
1514
1515
1516 ** Signature verification
1517    :PROPERTIES:
1518    :CUSTOM_ID: howto-basic-verification
1519    :END:
1520
1521 Essentially there are two principal methods of verification of a
1522 signature.  The first of these is for use with the normal or default
1523 signing method and for clear-signed messages.  The second is for use
1524 with files and data with detached signatures.
1525
1526 The following example is intended for use with the default signing
1527 method where the file was not ASCII armoured:
1528
1529 #+BEGIN_SRC python -i
1530 import gpg
1531 import time
1532
1533 filename = "statement.txt"
1534 gpg_file = "statement.txt.gpg"
1535
1536 c = gpg.Context()
1537
1538 try:
1539     data, result = c.verify(open(gpg_file))
1540     verified = True
1541 except gpg.errors.BadSignatures as e:
1542     verified = False
1543     print(e)
1544
1545 if verified is True:
1546     for i in range(len(result.signatures)):
1547         sign = result.signatures[i]
1548         print("""Good signature from:
1549 {0}
1550 with key {1}
1551 made at {2}
1552 """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
1553            time.ctime(sign.timestamp)))
1554 else:
1555     pass
1556 #+END_SRC
1557
1558 Whereas this next example, which is almost identical would work with
1559 normal ASCII armoured files and with clear-signed files:
1560
1561 #+BEGIN_SRC python -i
1562 import gpg
1563 import time
1564
1565 filename = "statement.txt"
1566 asc_file = "statement.txt.asc"
1567
1568 c = gpg.Context()
1569
1570 try:
1571     data, result = c.verify(open(asc_file))
1572     verified = True
1573 except gpg.errors.BadSignatures as e:
1574     verified = False
1575     print(e)
1576
1577 if verified is True:
1578     for i in range(len(result.signatures)):
1579         sign = result.signatures[i]
1580         print("""Good signature from:
1581 {0}
1582 with key {1}
1583 made at {2}
1584 """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
1585            time.ctime(sign.timestamp)))
1586 else:
1587     pass
1588 #+END_SRC
1589
1590 In both of the previous examples it is also possible to compare the
1591 original data that was signed against the signed data in =data= to see
1592 if it matches with something like this:
1593
1594 #+BEGIN_SRC python -i
1595 with open(filename, "rb") as afile:
1596     text = afile.read()
1597
1598 if text == data:
1599     print("Good signature.")
1600 else:
1601     pass
1602 #+END_SRC
1603
1604 The following two examples, however, deal with detached signatures.
1605 With his method of verification the data that was signed does not get
1606 returned since it is already being explicitly referenced in the first
1607 argument of =c.verify=.  So =data= is =None= and only the information
1608 in =result= is available.
1609
1610 #+BEGIN_SRC python -i
1611 import gpg
1612 import time
1613
1614 filename = "statement.txt"
1615 sig_file = "statement.txt.sig"
1616
1617 c = gpg.Context()
1618
1619 try:
1620     data, result = c.verify(open(filename), open(sig_file))
1621     verified = True
1622 except gpg.errors.BadSignatures as e:
1623     verified = False
1624     print(e)
1625
1626 if verified is True:
1627     for i in range(len(result.signatures)):
1628         sign = result.signatures[i]
1629         print("""Good signature from:
1630 {0}
1631 with key {1}
1632 made at {2}
1633 """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
1634            time.ctime(sign.timestamp)))
1635 else:
1636     pass
1637 #+END_SRC
1638
1639 #+BEGIN_SRC python -i
1640 import gpg
1641 import time
1642
1643 filename = "statement.txt"
1644 asc_file = "statement.txt.asc"
1645
1646 c = gpg.Context()
1647
1648 try:
1649     data, result = c.verify(open(filename), open(asc_file))
1650     verified = True
1651 except gpg.errors.BadSignatures as e:
1652     verified = False
1653     print(e)
1654
1655 if verified is True:
1656     for i in range(len(result.signatures)):
1657         sign = result.signatures[i]
1658         print("""Good signature from:
1659 {0}
1660 with key {1}
1661 made at {2}
1662 """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
1663            time.ctime(sign.timestamp)))
1664 else:
1665     pass
1666 #+END_SRC
1667
1668
1669 * Creating keys and subkeys
1670   :PROPERTIES:
1671   :CUSTOM_ID: key-generation
1672   :END:
1673
1674 The one thing, aside from GnuPG itself, that GPGME depends on, of
1675 course, is the keys themselves.  So it is necessary to be able to
1676 generate them and modify them by adding subkeys, revoking or disabling
1677 them, sometimes deleting them and doing the same for user IDs.
1678
1679 In the following examples a key will be created for the world's
1680 greatest secret agent, Danger Mouse.  Since Danger Mouse is a secret
1681 agent he needs to be able to protect information to =SECRET= level
1682 clearance, so his keys will be 3072-bit keys.
1683
1684 The pre-configured =gpg.conf= file which sets cipher, digest and other
1685 preferences contains the following configuration parameters:
1686
1687 #+BEGIN_SRC conf
1688   expert
1689   allow-freeform-uid
1690   allow-secret-key-import
1691   trust-model tofu+pgp
1692   tofu-default-policy unknown
1693   enable-large-rsa
1694   enable-dsa2
1695   cert-digest-algo SHA512
1696   default-preference-list TWOFISH CAMELLIA256 AES256 CAMELLIA192 AES192 CAMELLIA128 AES BLOWFISH IDEA CAST5 3DES SHA512 SHA384 SHA256 SHA224 RIPEMD160 SHA1 ZLIB BZIP2 ZIP Uncompressed
1697   personal-cipher-preferences TWOFISH CAMELLIA256 AES256 CAMELLIA192 AES192 CAMELLIA128 AES BLOWFISH IDEA CAST5 3DES
1698   personal-digest-preferences SHA512 SHA384 SHA256 SHA224 RIPEMD160 SHA1
1699   personal-compress-preferences ZLIB BZIP2 ZIP Uncompressed
1700 #+END_SRC
1701
1702
1703 ** Primary key
1704    :PROPERTIES:
1705    :CUSTOM_ID: keygen-primary
1706    :END:
1707
1708 Generating a primary key uses the =create_key= method in a Context.
1709 It contains multiple arguments and keyword arguments, including:
1710 =userid=, =algorithm=, =expires_in=, =expires=, =sign=, =encrypt=,
1711 =certify=, =authenticate=, =passphrase= and =force=.  The defaults for
1712 all of those except =userid=, =algorithm=, =expires_in=, =expires= and
1713 =passphrase= is =False=.  The defaults for =algorithm= and
1714 =passphrase= is =None=.  The default for =expires_in= is =0=.  The
1715 default for =expires= is =True=.  There is no default for =userid=.
1716
1717 If =passphrase= is left as =None= then the key will not be generated
1718 with a passphrase, if =passphrase= is set to a string then that will
1719 be the passphrase and if =passphrase= is set to =True= then gpg-agent
1720 will launch pinentry to prompt for a passphrase.  For the sake of
1721 convenience, these examples will keep =passphrase= set to =None=.
1722
1723 #+BEGIN_SRC python -i
1724 import gpg
1725
1726 c = gpg.Context()
1727
1728 c.home_dir = "~/.gnupg-dm"
1729 userid = "Danger Mouse <dm@secret.example.net>"
1730
1731 dmkey = c.create_key(userid, algorithm="rsa3072", expires_in=31536000,
1732                      sign=True, certify=True)
1733 #+END_SRC
1734
1735 One thing to note here is the use of setting the =c.home_dir=
1736 parameter.  This enables generating the key or keys in a different
1737 location.  In this case to keep the new key data created for this
1738 example in a separate location rather than adding it to existing and
1739 active key store data.  As with the default directory, =~/.gnupg=, any
1740 temporary or separate directory needs the permissions set to only
1741 permit access by the directory owner.  On posix systems this means
1742 setting the directory permissions to 700.
1743
1744 The =temp-homedir-config.py= script in the HOWTO examples directory
1745 will create an alternative homedir with these configuration options
1746 already set and the correct directory and file permissions.
1747
1748 The successful generation of the key can be confirmed via the returned
1749 =GenkeyResult= object, which includes the following data:
1750
1751 #+BEGIN_SRC python -i
1752 print("""
1753  Fingerprint:  {0}
1754  Primary Key:  {1}
1755   Public Key:  {2}
1756   Secret Key:  {3}
1757  Sub Key:  {4}
1758 User IDs:  {5}
1759 """.format(dmkey.fpr, dmkey.primary, dmkey.pubkey, dmkey.seckey, dmkey.sub,
1760            dmkey.uid))
1761 #+END_SRC
1762
1763 Alternatively the information can be confirmed using the command line
1764 program:
1765
1766 #+BEGIN_SRC shell
1767   bash-4.4$ gpg --homedir ~/.gnupg-dm -K
1768   ~/.gnupg-dm/pubring.kbx
1769   ----------------------
1770   sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
1771         177B7C25DB99745EE2EE13ED026D2F19E99E63AA
1772   uid           [ultimate] Danger Mouse <dm@secret.example.net>
1773
1774   bash-4.4$
1775 #+END_SRC
1776
1777 As with generating keys manually, to preconfigure expanded preferences
1778 for the cipher, digest and compression algorithms, the =gpg.conf= file
1779 must contain those details in the home directory in which the new key
1780 is being generated.  I used a cut down version of my own =gpg.conf=
1781 file in order to be able to generate this:
1782
1783 #+BEGIN_SRC shell
1784   bash-4.4$ gpg --homedir ~/.gnupg-dm --edit-key 177B7C25DB99745EE2EE13ED026D2F19E99E63AA showpref quit
1785   Secret key is available.
1786
1787   sec  rsa3072/026D2F19E99E63AA
1788        created: 2018-03-15  expires: 2019-03-15  usage: SC
1789        trust: ultimate      validity: ultimate
1790   [ultimate] (1). Danger Mouse <dm@secret.example.net>
1791
1792   [ultimate] (1). Danger Mouse <dm@secret.example.net>
1793        Cipher: TWOFISH, CAMELLIA256, AES256, CAMELLIA192, AES192, CAMELLIA128, AES, BLOWFISH, IDEA, CAST5, 3DES
1794        Digest: SHA512, SHA384, SHA256, SHA224, RIPEMD160, SHA1
1795        Compression: ZLIB, BZIP2, ZIP, Uncompressed
1796        Features: MDC, Keyserver no-modify
1797
1798   bash-4.4$
1799 #+END_SRC
1800
1801
1802 ** Subkeys
1803    :PROPERTIES:
1804    :CUSTOM_ID: keygen-subkeys
1805    :END:
1806
1807 Adding subkeys to a primary key is fairly similar to creating the
1808 primary key with the =create_subkey= method.  Most of the arguments
1809 are the same, but not quite all.  Instead of the =userid= argument
1810 there is now a =key= argument for selecting which primary key to add
1811 the subkey to.
1812
1813 In the following example an encryption subkey will be added to the
1814 primary key.  Since Danger Mouse is a security conscious secret agent,
1815 this subkey will only be valid for about six months, half the length
1816 of the primary key.
1817
1818 #+BEGIN_SRC python -i
1819 import gpg
1820
1821 c = gpg.Context()
1822 c.home_dir = "~/.gnupg-dm"
1823
1824 key = c.get_key(dmkey.fpr, secret=True)
1825 dmsub = c.create_subkey(key, algorithm="rsa3072", expires_in=15768000,
1826                         encrypt=True)
1827 #+END_SRC
1828
1829 As with the primary key, the results here can be checked with:
1830
1831 #+BEGIN_SRC python -i
1832 print("""
1833  Fingerprint:  {0}
1834  Primary Key:  {1}
1835   Public Key:  {2}
1836   Secret Key:  {3}
1837  Sub Key:  {4}
1838 User IDs:  {5}
1839 """.format(dmsub.fpr, dmsub.primary, dmsub.pubkey, dmsub.seckey, dmsub.sub,
1840            dmsub.uid))
1841 #+END_SRC
1842
1843 As well as on the command line with:
1844
1845 #+BEGIN_SRC shell
1846   bash-4.4$ gpg --homedir ~/.gnupg-dm -K
1847   ~/.gnupg-dm/pubring.kbx
1848   ----------------------
1849   sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
1850         177B7C25DB99745EE2EE13ED026D2F19E99E63AA
1851   uid           [ultimate] Danger Mouse <dm@secret.example.net>
1852   ssb   rsa3072 2018-03-15 [E] [expires: 2018-09-13]
1853
1854   bash-4.4$
1855 #+END_SRC
1856
1857
1858 ** User IDs
1859    :PROPERTIES:
1860    :CUSTOM_ID: keygen-uids
1861    :END:
1862
1863
1864 *** Adding User IDs
1865     :PROPERTIES:
1866     :CUSTOM_ID: keygen-uids-add
1867     :END:
1868
1869 By comparison to creating primary keys and subkeys, adding a new user
1870 ID to an existing key is much simpler.  The method used to do this is
1871 =key_add_uid= and the only arguments it takes are for the =key= and
1872 the new =uid=.
1873
1874 #+BEGIN_SRC python -i
1875 import gpg
1876
1877 c = gpg.Context()
1878 c.home_dir = "~/.gnupg-dm"
1879
1880 dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
1881 key = c.get_key(dmfpr, secret=True)
1882 uid = "Danger Mouse <danger.mouse@secret.example.net>"
1883
1884 c.key_add_uid(key, uid)
1885 #+END_SRC
1886
1887 Unsurprisingly the result of this is:
1888
1889 #+BEGIN_SRC shell
1890   bash-4.4$ gpg --homedir ~/.gnupg-dm -K
1891   ~/.gnupg-dm/pubring.kbx
1892   ----------------------
1893   sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
1894         177B7C25DB99745EE2EE13ED026D2F19E99E63AA
1895   uid           [ultimate] Danger Mouse <danger.mouse@secret.example.net>
1896   uid           [ultimate] Danger Mouse <dm@secret.example.net>
1897   ssb   rsa3072 2018-03-15 [E] [expires: 2018-09-13]
1898
1899   bash-4.4$
1900 #+END_SRC
1901
1902
1903 *** Revokinging User IDs
1904     :PROPERTIES:
1905     :CUSTOM_ID: keygen-uids-revoke
1906     :END:
1907
1908 Revoking a user ID is a fairly similar process, except that it uses
1909 the =key_revoke_uid= method.
1910
1911 #+BEGIN_SRC python -i
1912 import gpg
1913
1914 c = gpg.Context()
1915 c.home_dir = "~/.gnupg-dm"
1916
1917 dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
1918 key = c.get_key(dmfpr, secret=True)
1919 uid = "Danger Mouse <danger.mouse@secret.example.net>"
1920
1921 c.key_revoke_uid(key, uid)
1922 #+END_SRC
1923
1924
1925 ** Key certification
1926    :PROPERTIES:
1927    :CUSTOM_ID: key-sign
1928    :END:
1929
1930 Since key certification is more frequently referred to as key signing,
1931 the method used to perform this function is =key_sign=.
1932
1933 The =key_sign= method takes four arguments: =key=, =uids=,
1934 =expires_in= and =local=.  The default value of =uids= is =None= and
1935 which results in all user IDs being selected.  The default value of
1936 both =expires_in= and =local= is =False=; which results in the
1937 signature never expiring and being able to be exported.
1938
1939 The =key= is the key being signed rather than the key doing the
1940 signing.  To change the key doing the signing refer to the signing key
1941 selection above for signing messages and files.
1942
1943 If the =uids= value is not =None= then it must either be a string to
1944 match a single user ID or a list of strings to match multiple user
1945 IDs.  In this case the matching of those strings must be precise and
1946 it is case sensitive.
1947
1948 To sign Danger Mouse's key for just the initial user ID with a
1949 signature which will last a little over a month, do this:
1950
1951 #+BEGIN_SRC python -i
1952 import gpg
1953
1954 c = gpg.Context()
1955 uid = "Danger Mouse <dm@secret.example.net>"
1956
1957 dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
1958 key = c.get_key(dmfpr, secret=True)
1959 c.key_sign(key, uids=uid, expires_in=2764800)
1960 #+END_SRC
1961
1962
1963 * Miscellaneous work-arounds
1964   :PROPERTIES:
1965   :CUSTOM_ID: cheats-and-hacks
1966   :END:
1967
1968
1969 ** Group lines
1970    :PROPERTIES:
1971    :CUSTOM_ID: group-lines
1972    :END:
1973
1974 There is not yet an easy way to access groups configured in the
1975 gpg.conf file from within GPGME.  As a consequence these central
1976 groupings of keys cannot be shared amongst multiple programs, such as
1977 MUAs readily.
1978
1979 The following code, however, provides a work-around for obtaining this
1980 information in Python.
1981
1982 #+BEGIN_SRC python -i
1983 import subprocess
1984 import sys
1985
1986 if sys.platform == "win32":
1987     gpgconfcmd = "gpgconf.exe --list-options gpg"
1988 else:
1989     gpgconfcmd = "gpgconf --list-options gpg"
1990
1991 try:
1992     lines = subprocess.getoutput(gpgconfcmd).splitlines()
1993 except:
1994     process = subprocess.Popen(gpgconfcmd.split(), stdout=subprocess.PIPE)
1995     procom = process.communicate()
1996     if sys.version_info[0] == 2:
1997         lines = procom[0].splitlines()
1998     else:
1999         lines = procom[0].decode().splitlines()
2000
2001 for i in range(len(lines)):
2002     if lines[i].startswith("group") is True:
2003         line = lines[i]
2004     else:
2005         pass
2006
2007 groups = line.split(":")[-1].replace('"', '').split(',')
2008
2009 group_lines = []
2010 group_lists = []
2011
2012 for i in range(len(groups)):
2013     group_lines.append(groups[i].split("="))
2014     group_lists.append(groups[i].split("="))
2015
2016 for i in range(len(group_lists)):
2017     group_lists[i][1] = group_lists[i][1].split()
2018 #+END_SRC
2019
2020 The result of that code is that =group_lines= is a list of lists where
2021 =group_lines[i][0]= is the name of the group and =group_lines[i][1]=
2022 is the key IDs of the group as a string.
2023
2024 The =group_lists= result is very similar in that it is a list of
2025 lists.  The first part, =group_lists[i][0]= matches
2026 =group_lines[i][0]= as the name of the group, but =group_lists[i][1]=
2027 is the key IDs of the group as a string.
2028
2029 A demonstration of using the =groups.py= module is also available in
2030 the form of the executable =mutt-groups.py= script.  This second
2031 script reads all the group entries in a user's =gpg.conf= file and
2032 converts them into crypt-hooks suitable for use with the Mutt and
2033 Neomutt mail clients.
2034
2035
2036 * Copyright and Licensing
2037   :PROPERTIES:
2038   :CUSTOM_ID: copyright-and-license
2039   :END:
2040
2041
2042 ** Copyright (C) The GnuPG Project, 2018
2043    :PROPERTIES:
2044    :CUSTOM_ID: copyright
2045    :END:
2046
2047 Copyright © The GnuPG Project, 2018.
2048
2049
2050 ** License GPL compatible
2051    :PROPERTIES:
2052    :CUSTOM_ID: license
2053    :END:
2054
2055 This file is free software; as a special exception the author gives
2056 unlimited permission to copy and/or distribute it, with or without
2057 modifications, as long as this notice is preserved.
2058
2059 This file is distributed in the hope that it will be useful, but
2060 WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
2061 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
2062 PURPOSE.
2063
2064
2065 * Footnotes
2066
2067 [fn:1] =Short_History.org= and/or =Short_History.html=.
2068
2069 [fn:2] The =lang/python/docs/= directory in the GPGME source.
2070
2071 [fn:3] As Python 3.7 is a very recent release, it is not given
2072 priority over 3.6 yet, but will probably be prioritised by the release
2073 of Python 3.7.2.
2074
2075 [fn:4] Yes, even if you use virtualenv with everything you do in
2076 Python.  If you want to install this module as just your user account
2077 then you will need to manually configure, compile and install the
2078 /entire/ GnuPG stack as that user as well.  This includes libraries
2079 which are not often installed that way.  It can be done and there are
2080 circumstances under which it is worthwhile, but generally only on
2081 POSIX systems which utilise single user mode (some even require it).
2082
2083 [fn:5] You probably don't really want to do this.  Searching the
2084 keyservers for "gnupg.org" produces over 400 results, the majority of
2085 which aren't actually at the gnupg.org domain, but just included a
2086 comment regarding the project in their key somewhere.