7843965af81e8ccdb9b16bd6c95083f2ca2065b6
[gpgme.git] / lang / python / doc / rst / gpgme-python-howto.rst
1 .. _intro:
2
3 Introduction
4 ============
5
6 +-----------------+------------------------------------------+
7 | Version:        | 0.1.4                                    |
8 +-----------------+------------------------------------------+
9 | GPGME Version:  | 1.12.1                                   |
10 +-----------------+------------------------------------------+
11 | Author:         | Ben McGinnes <ben@gnupg.org>             |
12 +-----------------+------------------------------------------+
13 | Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
14 +-----------------+------------------------------------------+
15 | Language:       | Australian English, British English      |
16 +-----------------+------------------------------------------+
17 | Language codes: | en-AU, en-GB, en                         |
18 +-----------------+------------------------------------------+
19
20 This document provides basic instruction in how to use the GPGME Python
21 bindings to programmatically leverage the GPGME library.
22
23 .. _py2-vs-py3:
24
25 Python 2 versus Python 3
26 ------------------------
27
28 Though the GPGME Python bindings themselves provide support for both
29 Python 2 and 3, the focus is unequivocally on Python 3 and specifically
30 from Python 3.4 and above. As a consequence all the examples and
31 instructions in this guide use Python 3 code.
32
33 Much of it will work with Python 2, but much of it also deals with
34 Python 3 byte literals, particularly when reading and writing data.
35 Developers concentrating on Python 2.7, and possibly even 2.6, will need
36 to make the appropriate modifications to support the older string and
37 unicode types as opposed to bytes.
38
39 There are multiple reasons for concentrating on Python 3; some of which
40 relate to the immediate integration of these bindings, some of which
41 relate to longer term plans for both GPGME and the python bindings and
42 some of which relate to the impending EOL period for Python 2.7.
43 Essentially, though, there is little value in tying the bindings to a
44 version of the language which is a dead end and the advantages offered
45 by Python 3 over Python 2 make handling the data types with which GPGME
46 deals considerably easier.
47
48 .. _howto-python3-examples:
49
50 Examples
51 --------
52
53 All of the examples found in this document can be found as Python 3
54 scripts in the ``lang/python/examples/howto`` directory.
55
56 Unofficial Drafts
57 -----------------
58
59 In addition to shipping with each release of GPGME, there is a section
60 on locations to read or download `draft editions <#draft-editions>`__ of
61 this document from at the end of it. These are unofficial versions
62 produced in between major releases.
63
64 .. _new-stuff:
65
66 What\'s New
67 -----------
68
69 Full details of what is new are now available in the `What\'s
70 New <what-is-new.org>`__ file and archives of the preceding *What\'s
71 New* sections are available in the `What Was New <what-was-new>`__ file.
72
73 .. _new-stuff-1-13-0:
74
75 New in GPGME 1·13·0
76 ~~~~~~~~~~~~~~~~~~~
77
78 See the `What\'s New <what-is-new#new-stuff-1-13-0>`__ document for what
79 is new in version 1.13.0.
80
81 .. _new-stuff-1-12-0:
82
83 New in GPGME 1·12·0
84 ~~~~~~~~~~~~~~~~~~~
85
86 See the `What Was New <what-was-new#new-stuff-1-12-0>`__ document for
87 what was new in version 1.12.0.
88
89 GPGME Concepts
90 ==============
91
92 .. _gpgme-c-api:
93
94 A C API
95 -------
96
97 Unlike many modern APIs with which programmers will be more familiar
98 with these days, the GPGME API is a C API. The API is intended for use
99 by C coders who would be able to access its features by including the
100 ``gpgme.h`` header file with their own C source code and then access its
101 functions just as they would any other C headers.
102
103 This is a very effective method of gaining complete access to the API
104 and in the most efficient manner possible. It does, however, have the
105 drawback that it cannot be directly used by other languages without some
106 means of providing an interface to those languages. This is where the
107 need for bindings in various languages stems.
108
109 .. _gpgme-python-bindings:
110
111 Python bindings
112 ---------------
113
114 The Python bindings for GPGME provide a higher level means of accessing
115 the complete feature set of GPGME itself. It also provides a more
116 pythonic means of calling these API functions.
117
118 The bindings are generated dynamically with SWIG and the copy of
119 ``gpgme.h`` generated when GPGME is compiled.
120
121 This means that a version of the Python bindings is fundamentally tied
122 to the exact same version of GPGME used to generate that copy of
123 ``gpgme.h``.
124
125 .. _gpgme-python-bindings-diffs:
126
127 Difference between the Python bindings and other GnuPG Python packages
128 ----------------------------------------------------------------------
129
130 There have been numerous attempts to add GnuPG support to Python over
131 the years. Some of the most well known are listed here, along with what
132 differentiates them.
133
134 .. _diffs-python-gnupg:
135
136 The python-gnupg package maintained by Vinay Sajip
137 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
138
139 This is arguably the most popular means of integrating GPG with Python.
140 The package utilises the ``subprocess`` module to implement wrappers for
141 the ``gpg`` and ``gpg2`` executables normally invoked on the command
142 line (``gpg.exe`` and ``gpg2.exe`` on Windows).
143
144 The popularity of this package stemmed from its ease of use and
145 capability in providing the most commonly required features.
146
147 Unfortunately it has been beset by a number of security issues in the
148 past; most of which stemmed from using unsafe methods of accessing the
149 command line via the ``subprocess`` calls. While some effort has been
150 made over the last two to three years (as of 2018) to mitigate this,
151 particularly by no longer providing shell access through those
152 subprocess calls, the wrapper is still somewhat limited in the scope of
153 its GnuPG features coverage.
154
155 The python-gnupg package is available under the MIT license.
156
157 .. _diffs-isis-gnupg:
158
159 The gnupg package created and maintained by Isis Lovecruft
160 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
161
162 In 2015 Isis Lovecruft from the Tor Project forked and then
163 re-implemented the python-gnupg package as just gnupg. This new package
164 also relied on subprocess to call the ``gpg`` or ``gpg2`` binaries, but
165 did so somewhat more securely.
166
167 The naming and version numbering selected for this package, however,
168 resulted in conflicts with the original python-gnupg and since its
169 functions were called in a different manner to python-gnupg, the release
170 of this package also resulted in a great deal of consternation when
171 people installed what they thought was an upgrade that subsequently
172 broke the code relying on it.
173
174 The gnupg package is available under the GNU General Public License
175 version 3.0 (or any later version).
176
177 .. _diffs-pyme:
178
179 The PyME package maintained by Martin Albrecht
180 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
181
182 This package is the origin of these bindings, though they are somewhat
183 different now. For details of when and how the PyME package was folded
184 back into GPGME itself see the `Short History <short-history.org>`__
185 document. [1]_
186
187 The PyME package was first released in 2002 and was also the first
188 attempt to implement a low level binding to GPGME. In doing so it
189 provided access to considerably more functionality than either the
190 ``python-gnupg`` or ``gnupg`` packages.
191
192 The PyME package is only available for Python 2.6 and 2.7.
193
194 Porting the PyME package to Python 3.4 in 2015 is what resulted in it
195 being folded into the GPGME project and the current bindings are the end
196 result of that effort.
197
198 The PyME package is available under the same dual licensing as GPGME
199 itself: the GNU General Public License version 2.0 (or any later
200 version) and the GNU Lesser General Public License version 2.1 (or any
201 later version).
202
203 .. _gpgme-python-install:
204
205 GPGME Python bindings installation
206 ==================================
207
208 .. _do-not-use-pypi:
209
210 No PyPI
211 -------
212
213 Most third-party Python packages and modules are available and
214 distributed through the Python Package Installer, known as PyPI.
215
216 Due to the nature of what these bindings are and how they work, it is
217 infeasible to install the GPGME Python bindings in the same way.
218
219 This is because the bindings use SWIG to dynamically generate C bindings
220 against ``gpgme.h`` and ``gpgme.h`` is generated from ``gpgme.h.in`` at
221 compile time when GPGME is built from source. Thus to include a package
222 in PyPI which actually built correctly would require either statically
223 built libraries for every architecture bundled with it or a full
224 implementation of C for each architecture.
225
226 See the additional notes regarding `CFFI and SWIG <#snafu-cffi>`__ at
227 the end of this section for further details.
228
229 .. _gpgme-python-requirements:
230
231 Requirements
232 ------------
233
234 The GPGME Python bindings only have three requirements:
235
236 #. A suitable version of Python 2 or Python 3. With Python 2 that means
237    CPython 2.7 and with Python 3 that means CPython 3.4 or higher.
238 #. `SWIG <https://www.swig.org>`__.
239 #. GPGME itself. Which also means that all of GPGME\'s dependencies must
240    be installed too.
241
242 .. _gpgme-python-recommendations:
243
244 Recommended Additions
245 ~~~~~~~~~~~~~~~~~~~~~
246
247 Though none of the following are absolute requirements, they are all
248 recommended for use with the Python bindings. In some cases these
249 recommendations refer to which version(s) of CPython to use the bindings
250 with, while others refer to third party modules which provide a
251 significant advantage in some way.
252
253 #. If possible, use Python 3 instead of 2.
254 #. Favour a more recent version of Python since even 3.4 is due to reach
255    EOL soon. In production systems and services, Python 3.6 should be
256    robust enough to be relied on.
257 #. If possible add the following Python modules which are not part of
258    the standard library:
259    `Requests <http://docs.python-requests.org/en/latest/index.html>`__,
260    `Cython <https://cython.org/>`__,
261    `Pendulum <https://pendulum.eustace.io/>`__ and
262    `hkp4py <https://github.com/Selfnet/hkp4py>`__.
263
264 Chances are quite high that at least the first one and maybe two of
265 those will already be installed.
266
267 Note that, as with Cython, some of advanced use case scenarios will
268 bring with them additional requirements. Most of these will be fairly
269 well known and commonly installed ones, however, which are in many cases
270 likely to have already been installed on many systems or be familiar to
271 Python programmers.
272
273 Installation
274 ------------
275
276 Installing the Python bindings is effectively achieved by compiling and
277 installing GPGME itself.
278
279 Once SWIG is installed with Python and all the dependencies for GPGME
280 are installed you only need to confirm that the version(s) of Python you
281 want the bindings installed for are in your ``$PATH``.
282
283 By default GPGME will attempt to install the bindings for the most
284 recent or highest version number of Python 2 and Python 3 it detects in
285 ``$PATH``. It specifically checks for the ``python`` and ``python3``
286 executables first and then checks for specific version numbers.
287
288 For Python 2 it checks for these executables in this order: ``python``,
289 ``python2`` and ``python2.7``.
290
291 For Python 3 it checks for these executables in this order: ``python3``,
292 ``python3.7``, ``python3.6``, ``python3.5`` and ``python3.4``. [2]_
293
294 On systems where ``python`` is actually ``python3`` and not ``python2``
295 it may be possible that ``python2`` may be overlooked, but there have
296 been no reports of that actually occurring as yet.
297
298 In the three months or so since the release of Python 3.7.0 there has
299 been extensive testing and work with these bindings with no issues
300 specifically relating to the new version of Python or any of the new
301 features of either the language or the bindings. This has also been the
302 case with Python 3.7.1rc1. With that in mind and given the release of
303 Python 3.7.1 is scheduled for around the same time as GPGME 1.12.0, the
304 order of preferred Python versions has been changed to move Python 3.7
305 ahead of Python 3.6.
306
307 .. _install-gpgme:
308
309 Installing GPGME
310 ~~~~~~~~~~~~~~~~
311
312 See the GPGME ``README`` file for details of how to install GPGME from
313 source.
314
315 .. _snafu:
316
317 Known Issues
318 ------------
319
320 There are a few known issues with the current build process and the
321 Python bindings. For the most part these are easily addressed should
322 they be encountered.
323
324 .. _snafu-a-swig-of-this-builds-character:
325
326 Breaking Builds
327 ~~~~~~~~~~~~~~~
328
329 Occasionally when installing GPGME with the Python bindings included it
330 may be observed that the ``make`` portion of that process induces a
331 large very number of warnings and, eventually errors which end that part
332 of the build process. Yet following that with ``make check`` and
333 ``make install`` appears to work seamlessly.
334
335 The cause of this is related to the way SWIG needs to be called to
336 dynamically generate the C bindings for GPGME in the first place. So the
337 entire process will always produce ``lang/python/python2-gpg/`` and
338 ``lang/python/python3-gpg/`` directories. These should contain the build
339 output generated during compilation, including the complete bindings and
340 module installed into ``site-packages``.
341
342 Occasionally the errors in the early part or some other conflict (e.g.
343 not installing as **root** or **su**) may result in nothing being
344 installed to the relevant ``site-packages`` directory and the build
345 directory missing a lot of expected files. Even when this occurs, the
346 solution is actually quite simple and will always work.
347
348 That solution is simply to run the following commands as either the
349 **root** user or prepended with ``sudo -H``\  [3]_ in the
350 ``lang/python/`` directory:
351
352 .. code:: shell
353
354    /path/to/pythonX.Y setup.py build
355    /path/to/pythonX.Y setup.py build
356    /path/to/pythonX.Y setup.py install
357
358 Yes, the build command does need to be run twice. Yes, you still need to
359 run the potentially failing or incomplete steps during the
360 ``configure``, ``make`` and ``make install`` steps with installing
361 GPGME. This is because those steps generate a lot of essential files
362 needed, both by and in order to create, the bindings (including both the
363 ``setup.py`` and ``gpgme.h`` files).
364
365 #. IMPORTANT Note
366
367    If specifying a selected number of languages to create bindings for,
368    try to leave Python last. Currently the majority of the other
369    language bindings are also preceding Python of either version when
370    listed alphabetically and so that just happens by default currently.
371
372    If Python is set to precede one of the other languages then it is
373    possible that the errors described here may interrupt the build
374    process before generating bindings for those other languages. In
375    these cases it may be preferable to configure all preferred language
376    bindings separately with alternative ``configure`` steps for GPGME
377    using the ``--enable-languages=$LANGUAGE`` option.
378
379 .. _snafu-lessons-for-the-lazy:
380
381 Reinstalling Responsibly
382 ~~~~~~~~~~~~~~~~~~~~~~~~
383
384 Regardless of whether you\'re installing for one version of Python or
385 several, there will come a point where reinstallation is required. With
386 most Python module installations, the installed files go into the
387 relevant site-packages directory and are then forgotten about. Then the
388 module is upgraded, the new files are copied over the old and that\'s
389 the end of the matter.
390
391 While the same is true of these bindings, there have been intermittent
392 issues observed on some platforms which have benefited significantly
393 from removing all the previous installations of the bindings before
394 installing the updated versions.
395
396 Removing the previous version(s) is simply a matter of changing to the
397 relevant ``site-packages`` directory for the version of Python in
398 question and removing the ``gpg/`` directory and any accompanying
399 egg-info files for that module.
400
401 In most cases this will require root or administration privileges on the
402 system, but the same is true of installing the module in the first
403 place.
404
405 .. _snafu-the-full-monty:
406
407 Multiple installations
408 ~~~~~~~~~~~~~~~~~~~~~~
409
410 For a variety of reasons it may be either necessary or just preferable
411 to install the bindings to alternative installed Python versions which
412 meet the requirements of these bindings.
413
414 On POSIX systems this will generally be most simply achieved by running
415 the manual installation commands (build, build, install) as described in
416 the previous section for each Python installation the bindings need to
417 be installed to.
418
419 As per the SWIG documentation: the compilers, libraries and runtime used
420 to build GPGME and the Python Bindings **must** match those used to
421 compile Python itself, including the version number(s) (at least going
422 by major version numbers and probably minor numbers too).
423
424 On most POSIX systems, including OS X, this will very likely be the case
425 in most, if not all, cases.
426
427 Note that from GPGME
428 `1.12.1 <https://dev.gnupg.org/rMff6ff616aea6f59b7f2ce1176492850ecdf3851e>`__
429 the default installation installs to each version of Python it can find
430 first. That is that it will currently install for the first copies of
431 Python versions 2.7, 3.4, 3.5, 3.6, 3.7 and 3.8 (dev branch) that it
432 finds. Usually this will be in the same prefix as GPGME itself, but is
433 dictated by the ``$PATH`` when the installation is performed. The above
434 instructions can still be performed on other python installations which
435 the installer does not find, including alternative prefixes.
436
437 .. _snafu-runtime-not-funtime:
438
439 Won\'t Work With Windows
440 ~~~~~~~~~~~~~~~~~~~~~~~~
441
442 There are semi-regular reports of Windows users having considerable
443 difficulty in installing and using the Python bindings at all. Very
444 often, possibly even always, these reports come from Cygwin users and/or
445 MinGW users and/or Msys2 users. Though not all of them have been
446 confirmed, it appears that these reports have also come from people who
447 installed Python using the Windows installer files from the `Python
448 website <https://python.org>`__ (i.e. mostly MSI installers, sometimes
449 self-extracting ``.exe`` files).
450
451 The Windows versions of Python are not built using Cygwin, MinGW or
452 Msys2; they\'re built using Microsoft Visual Studio. Furthermore the
453 version used is *considerably* more advanced than the version which
454 MinGW obtained a small number of files from many years ago in order to
455 be able to compile anything at all. Not only that, but there are changes
456 to the version of Visual Studio between some micro releases, though that
457 is is particularly the case with Python 2.7, since it has been kept
458 around far longer than it should have been.
459
460 There are two theoretical solutions to this issue:
461
462 #. Compile and install the GnuPG stack, including GPGME and the Python
463    bindings using the same version of Microsoft Visual Studio used by
464    the Python Foundation to compile the version of Python installed.
465
466    If there are multiple versions of Python then this will need to be
467    done with each different version of Visual Studio used for those
468    versions of Python.
469
470 #. Compile and install Python using the same tools used by choice, such
471    as MinGW or Msys2.
472
473 Do **not** use the official Windows installer for Python unless
474 following the first method.
475
476 In this type of situation it may even be for the best to accept that
477 there are less limitations on permissive software than free software and
478 simply opt to use a recent version of the Community Edition of Microsoft
479 Visual Studio to compile and build all of it, no matter what.
480
481 Investigations into the extent or the limitations of this issue are
482 ongoing.
483
484 The following table lists the version of Microsoft Visual Studio which
485 needs to be used when compiling GPGME and the Python bindings with each
486 version of the CPython binary released `for
487 Windows <https://www.python.org/downloads/windows/>`__:
488
489 +---------+------------------------+------------------+
490 | CPython | Microsoft product name | runtime filename |
491 +---------+------------------------+------------------+
492 | 2.7.6   | Visual Studio 2008     | MSVCR90.DLL      |
493 +---------+------------------------+------------------+
494 | 3.4.0   | Visual Studio 2010     | MSVCR100.DLL     |
495 +---------+------------------------+------------------+
496 | 3.5.0   | Visual Studio 2015     | **see below**    |
497 +---------+------------------------+------------------+
498 | 3.6.0   | Visual Studio 2015     | **see below**    |
499 +---------+------------------------+------------------+
500 | 3.7.0   | Visual Studio 2017\*   | **see below**    |
501 +---------+------------------------+------------------+
502
503 It is important to note that MingW and Msys2 ship with the Visual C
504 runtime from Microsoft Visual Studio 2005 and are thus **incompatible**
505 with all the versions of CPython which can be used with the GPGME Python
506 bindings.
507
508 It is also important to note that from CPython 3.5 onwards, the Python
509 Foundation has adopted the reworking of the Visual C runtime which was
510 performed for Visual Studio 2015 and aimed at resolving many of these
511 kinds of issues. Much greater detail on these issues and the correct
512 file(s) to link to are available from Matthew Brett\'s invaluable page,
513 `Using Microsoft Visual C with
514 Python <https://matthew-brett.github.io/pydagogue/python_msvc.html>`__.
515 It is also worth reading the Microsoft Developer Network blog post on
516 `the universal
517 CRT <http://blogs.msdn.com/b/vcblog/archive/2015/03/03/introducing-the-universal-crt.aspx>`__
518 and Steve Dower\'s blog posts on Python extensions (`part
519 1 <http://stevedower.id.au/blog/building-for-python-3-5>`__ and `part
520 2 <http://stevedower.id.au/blog/building-for-python-3-5-part-two>`__).
521
522 The second of those two posts by Steve Dower contains the details of
523 specific configuration options required for compiling anything to be
524 used with official CPython releases. In addition to those configuration
525 and compiler settings to use, the versions of Visual Studio prior to
526 Visual Studio 2015 did not support 64-bit systems by default. So
527 compiling a 64-bit version of these bindings for a 64-bit version of
528 CPython 2.7 or 3.4 requires additional work.
529
530 In addition to the blog posts, the `Windows
531 compilers <https://wiki.python.org/moin/WindowsCompilers>`__ wiki page
532 on the CPython wiki is another essential reference on the relevant
533 versions of Visual Studio to use and the degree of compatibility with
534 CPython releases.
535
536 Eventually someone will ask why there isn\'t an installable binary for
537 Windows, which the GPGME of the licenses do not preclude as long as the
538 source code is available in conjunction with such a release.
539
540 The sheer number of versions of Visual Studio in conjunction with
541 differing configuration options depending on the target Windows version
542 and whether the architecture is 64-bit or 32-bit makes it difficult to
543 provide a correct binary installer for Windows users. At the bare
544 minimum doing so would require the GnuPG project compile ten different
545 versions of the bindings with each release; both 32-bit and 64-bit
546 versions for CPython 2.7 and 3.4, with 64-bit versions for both x86-64
547 (i.e. Intel and AMD) and ARM architectures for CPython 3.5, 3.6, 3.7 and
548 later releases. That\'s the bare **minimum**, it\'d probably be higher.
549
550 Additionally, with only a binary installation used in conjunction with
551 the CPython installer from ``python.org`` the advanced options available
552 which utilise `Cython <#cython>`__ will not be able to be used at all.
553 Cython depends on being able to compile the C code it generates and that
554 too would need to utilise a matching runtime to both the installed
555 version of CPython and these bindings in order to work with the
556 bindings.
557
558 Considering all of that, what do we recommend?
559
560 #. Use a recent version of CPython; at least 3.5, but ideally 3.6 or
561    later.
562
563 #. Use Visual Studio 2015 or the standalone build tools for Visual
564    Studio 2017 (or later).
565
566 #. Compile both CPython and GPGME with these bindings using the tools
567    selected in step 2.
568
569 #. Ignore MingW, Msys2 and the official CPython binary installers.
570
571 #. Be thankful the answer to this question wasn\'t simply to say
572    something like, "install Linux" or "install FreeBSD" (or even
573    Apple\'s OS X).
574
575 .. _snafu-cffi:
576
577 CFFI is the Best™ and GPGME should use it instead of SWIG
578 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
579
580 There are many reasons for favouring
581 `CFFI <https://cffi.readthedocs.io/en/latest/overview.html>`__ and
582 proponents of it are quite happy to repeat these things as if all it
583 would take to switch from SWIG to CFFI is repeating that list as if it
584 were a new concept.
585
586 The fact is that there are things which Python\'s CFFI implementation
587 cannot handle in the GPGME C code. Beyond that there are features of
588 SWIG which are simply not available with CFFI at all. SWIG generates the
589 bindings to Python using the ``gpgme.h`` file, but that file is not a
590 single version shipped with each release, it too is generated when GPGME
591 is compiled.
592
593 CFFI is currently unable to adapt to such a potentially mutable
594 codebase. If there were some means of applying SWIG\'s dynamic code
595 generation to produce the Python/CFFI API modes of accessing the GPGME
596 libraries (or the source source code directly), but such a thing does
597 not exist yet either and it currently appears that work is needed in at
598 least one of CFFI\'s dependencies before any of this can be addressed.
599
600 So if you\'re a massive fan of CFFI; that\'s great, but if you want this
601 project to switch to CFFI then rather than just insisting that it
602 should, I\'d suggest you volunteer to bring CFFI up to the level this
603 project needs.
604
605 If you\'re actually seriously considering doing so, then I\'d suggest
606 taking the ``gpgme-tool.c`` file in the GPGME ``src/`` directory and
607 getting that to work with any of the CFFI API methods (not the ABI
608 methods, they\'ll work with pretty much anything). When you start
609 running into trouble with \"ifdefs\" then you\'ll know what sort of
610 things are lacking. That doesn\'t even take into account the amount of
611 work saved via SWIG\'s code generation techniques either.
612
613 .. _snafu-venv:
614
615 Virtualised Environments
616 ~~~~~~~~~~~~~~~~~~~~~~~~
617
618 It is fairly common practice amongst Python developers to, as much as
619 possible, use packages like virtualenv to keep various things that are
620 to be installed from interfering with each other. Given how much of the
621 GPGME bindings is often at odds with the usual pythonic way of doing
622 things, it stands to reason that this would be called into question too.
623
624 As it happens the answer as to whether or not the bindings can be used
625 with virtualenv, the answer is both yes and no.
626
627 In general we recommend installing to the relevant path and matching
628 prefix of GPGME itself. Which means that when GPGME, and ideally the
629 rest of the GnuPG stack, is installed to a prefix like ``/usr/local`` or
630 ``/opt/local`` then the bindings would need to be installed to the main
631 Python installation and not a virtualised abstraction. Attempts to
632 separate the two in the past have been known to cause weird and
633 intermittent errors ranging from minor annoyances to complete failures
634 in the build process.
635
636 As a consequence we only recommend building with and installing to the
637 main Python installations within the same prefix as GPGME is installed
638 to or which are found by GPGME\'s configuration stage immediately prior
639 to running the make commands. Which is exactly what the compiling and
640 installing process of GPGME does by default.
641
642 Once that is done, however, it appears that a copy of the compiled
643 module may be installed into a virtualenv of the same major and minor
644 version matching the build. Alternatively it is possible to utilise a
645 ``sites.pth`` file in the ``site-packages/`` directory of a virtualenv
646 installation, which links back to the system installations corresponding
647 directory in order to import anything installed system wide. This may or
648 may not be appropriate on a case by case basis.
649
650 Though extensive testing of either of these options is not yet complete,
651 preliminary testing of them indicates that both are viable as long as
652 the main installation is complete. Which means that certain other
653 options normally restricted to virtual environments are also available,
654 including integration with pythonic test suites (e.g.
655 `pytest <https://docs.pytest.org/en/latest/index.html>`__) and other
656 large projects.
657
658 That said, it is worth reiterating the warning regarding non-standard
659 installations. If one were to attempt to install the bindings only to a
660 virtual environment without somehow also including the full GnuPG stack
661 (or enough of it as to include GPGME) then it is highly likely that
662 errors would be encountered at some point and more than a little likely
663 that the build process itself would break.
664
665 If a degree of separation from the main operating system is still
666 required in spite of these warnings, then consider other forms of
667 virtualisation. Either a virtual machine (e.g.
668 `VirtualBox <https://www.virtualbox.org/>`__), a hardware emulation
669 layer (e.g. `QEMU <https://www.qemu.org/>`__) or an application
670 container (e.g. `Docker <https://www.docker.com/why-docker>`__).
671
672 Finally it should be noted that the limited tests conducted thus far
673 have been using the ``virtualenv`` command in a new directory to create
674 the virtual python environment. As opposed to the standard ``python3
675 -m venv`` and it is possible that this will make a difference depending
676 on the system and version of Python in use. Another option is to run the
677 command ``python3 -m virtualenv /path/to/install/virtual/thingy``
678 instead.
679
680 .. _howto-fund-a-mental:
681
682 Fundamentals
683 ============
684
685 Before we can get to the fun stuff, there are a few matters regarding
686 GPGME\'s design which hold true whether you\'re dealing with the C code
687 directly or these Python bindings.
688
689 .. _no-rest-for-the-wicked:
690
691 No REST
692 -------
693
694 The first part of which is or will be fairly blatantly obvious upon
695 viewing the first example, but it\'s worth reiterating anyway. That
696 being that this API is **not** a REST API. Nor indeed could it ever be
697 one.
698
699 Most, if not all, Python programmers (and not just Python programmers)
700 know how easy it is to work with a RESTful API. In fact they\'ve become
701 so popular that many other APIs attempt to emulate REST-like behaviour
702 as much as they are able. Right down to the use of JSON formatted output
703 to facilitate the use of their API without having to retrain developers.
704
705 This API does not do that. It would not be able to do that and also
706 provide access to the entire C API on which it\'s built. It does,
707 however, provide a very pythonic interface on top of the direct bindings
708 and it\'s this pythonic layer that this HOWTO deals with.
709
710 .. _howto-get-context:
711
712 Context
713 -------
714
715 One of the reasons which prevents this API from being RESTful is that
716 most operations require more than one instruction to the API to perform
717 the task. Sure, there are certain functions which can be performed
718 simultaneously, particularly if the result known or strongly anticipated
719 (e.g. selecting and encrypting to a key known to be in the public
720 keybox).
721
722 There are many more, however, which cannot be manipulated so readily:
723 they must be performed in a specific sequence and the result of one
724 operation has a direct bearing on the outcome of subsequent operations.
725 Not merely by generating an error either.
726
727 When dealing with this type of persistent state on the web, full of both
728 the RESTful and REST-like, it\'s most commonly referred to as a session.
729 In GPGME, however, it is called a context and every operation type has
730 one.
731
732 .. _howto-keys:
733
734 Working with keys
735 =================
736
737 .. _howto-keys-selection:
738
739 Key selection
740 -------------
741
742 Selecting keys to encrypt to or to sign with will be a common occurrence
743 when working with GPGMe and the means available for doing so are quite
744 simple.
745
746 They do depend on utilising a Context; however once the data is recorded
747 in another variable, that Context does not need to be the same one which
748 subsequent operations are performed.
749
750 The easiest way to select a specific key is by searching for that key\'s
751 key ID or fingerprint, preferably the full fingerprint without any
752 spaces in it. A long key ID will probably be okay, but is not advised
753 and short key IDs are already a problem with some being generated to
754 match specific patterns. It does not matter whether the pattern is upper
755 or lower case.
756
757 So this is the best method:
758
759 .. code:: python
760
761    import gpg
762
763    k = gpg.Context().keylist(pattern="258E88DCBD3CD44D8E7AB43F6ECB6AF0DEADBEEF")
764    keys = list(k)
765
766 This is passable and very likely to be common:
767
768 .. code:: python
769
770    import gpg
771
772    k = gpg.Context().keylist(pattern="0x6ECB6AF0DEADBEEF")
773    keys = list(k)
774
775 And this is a really bad idea:
776
777 .. code:: python
778
779    import gpg
780
781    k = gpg.Context().keylist(pattern="0xDEADBEEF")
782    keys = list(k)
783
784 Alternatively it may be that the intention is to create a list of keys
785 which all match a particular search string. For instance all the
786 addresses at a particular domain, like this:
787
788 .. code:: python
789
790    import gpg
791
792    ncsc = gpg.Context().keylist(pattern="ncsc.mil")
793    nsa = list(ncsc)
794
795 .. _howto-keys-counting:
796
797 Counting keys
798 ~~~~~~~~~~~~~
799
800 Counting the number of keys in your public keybox (``pubring.kbx``), the
801 format which has superseded the old keyring format (``pubring.gpg`` and
802 ``secring.gpg``), or the number of secret keys is a very simple task.
803
804 .. code:: python
805
806    import gpg
807
808    c = gpg.Context()
809    seckeys = c.keylist(pattern=None, secret=True)
810    pubkeys = c.keylist(pattern=None, secret=False)
811
812    seclist = list(seckeys)
813    secnum = len(seclist)
814
815    publist = list(pubkeys)
816    pubnum = len(publist)
817
818    print("""
819      Number of secret keys:  {0}
820      Number of public keys:  {1}
821    """.format(secnum, pubnum))
822
823 NOTE: The `Cython <#cython>`__ introduction in the `Advanced and
824 Experimental <#advanced-use>`__ section uses this same key counting code
825 with Cython to demonstrate some areas where Cython can improve
826 performance even with the bindings. Users with large public keyrings or
827 keyboxes, for instance, should consider these options if they are
828 comfortable with using Cython.
829
830 .. _howto-get-key:
831
832 Get key
833 -------
834
835 An alternative method of getting a single key via its fingerprint is
836 available directly within a Context with ``Context().get_key``. This is
837 the preferred method of selecting a key in order to modify it, sign or
838 certify it and for obtaining relevant data about a single key as a part
839 of other functions; when verifying a signature made by that key, for
840 instance.
841
842 By default this method will select public keys, but it can select secret
843 keys as well.
844
845 This first example demonstrates selecting the current key of Werner
846 Koch, which is due to expire at the end of 2018:
847
848 .. code:: python
849
850    import gpg
851
852    fingerprint = "80615870F5BAD690333686D0F2AD85AC1E42B367"
853    key = gpg.Context().get_key(fingerprint)
854
855 Whereas this example demonstrates selecting the author\'s current key
856 with the ``secret`` key word argument set to ``True``:
857
858 .. code:: python
859
860    import gpg
861
862    fingerprint = "DB4724E6FA4286C92B4E55C4321E4E2373590E5D"
863    key = gpg.Context().get_key(fingerprint, secret=True)
864
865 It is, of course, quite possible to select expired, disabled and revoked
866 keys with this function, but only to effectively display information
867 about those keys.
868
869 It is also possible to use both unicode or string literals and byte
870 literals with the fingerprint when getting a key in this way.
871
872 .. _howto-import-key:
873
874 Importing keys
875 --------------
876
877 Importing keys is possible with the ``key_import()`` method and takes
878 one argument which is a bytes literal object containing either the
879 binary or ASCII armoured key data for one or more keys.
880
881 The following example retrieves one or more keys from the SKS keyservers
882 via the web using the requests module. Since requests returns the
883 content as a bytes literal object, we can then use that directly to
884 import the resulting data into our keybox.
885
886 .. code:: python
887
888    import gpg
889    import os.path
890    import requests
891
892    c = gpg.Context()
893    url = "https://sks-keyservers.net/pks/lookup"
894    pattern = input("Enter the pattern to search for key or user IDs: ")
895    payload = {"op": "get", "search": pattern}
896
897    r = requests.get(url, verify=True, params=payload)
898    result = c.key_import(r.content)
899
900    if result is not None and hasattr(result, "considered") is False:
901        print(result)
902    elif result is not None and hasattr(result, "considered") is True:
903        num_keys = len(result.imports)
904        new_revs = result.new_revocations
905        new_sigs = result.new_signatures
906        new_subs = result.new_sub_keys
907        new_uids = result.new_user_ids
908        new_scrt = result.secret_imported
909        nochange = result.unchanged
910        print("""
911      The total number of keys considered for import was:  {0}
912
913         Number of keys revoked:  {1}
914       Number of new signatures:  {2}
915          Number of new subkeys:  {3}
916         Number of new user IDs:  {4}
917      Number of new secret keys:  {5}
918       Number of unchanged keys:  {6}
919
920      The key IDs for all considered keys were:
921    """.format(num_keys, new_revs, new_sigs, new_subs, new_uids, new_scrt,
922               nochange))
923        for i in range(num_keys):
924            print("{0}\n".format(result.imports[i].fpr))
925    else:
926        pass
927
928 NOTE: When searching for a key ID of any length or a fingerprint
929 (without spaces), the SKS servers require the the leading ``0x``
930 indicative of hexadecimal be included. Also note that the old short key
931 IDs (e.g. ``0xDEADBEEF``) should no longer be used due to the relative
932 ease by which such key IDs can be reproduced, as demonstrated by the
933 Evil32 Project in 2014 (which was subsequently exploited in 2016).
934
935 Testing for whether a string in any given search is or may be a
936 hexadecimal value which may be missing the leading ``0x`` is a simple
937 matter of using a try/except statement which attempts to convert the
938 string as hex to an integer and then back to hex; then using that to
939 search with. Raising a ValueError simply results in treating the string
940 as a string. This is the method and logic utilised in the
941 ``import-keys-hkp.py`` script (see below).
942
943 .. _import-protonmail:
944
945 Working with ProtonMail
946 ~~~~~~~~~~~~~~~~~~~~~~~
947
948 Here is a variation on the example above which checks the constrained
949 ProtonMail keyserver for ProtonMail public keys.
950
951 .. code:: python
952
953    import gpg
954    import requests
955    import sys
956
957    print("""
958    This script searches the ProtonMail key server for the specified key and
959    imports it.
960    """)
961
962    c = gpg.Context(armor=True)
963    url = "https://api.protonmail.ch/pks/lookup"
964    ksearch = []
965
966    if len(sys.argv) >= 2:
967        keyterm = sys.argv[1]
968    else:
969        keyterm = input("Enter the key ID, UID or search string: ")
970
971    if keyterm.count("@") == 2 and keyterm.startswith("@") is True:
972        ksearch.append(keyterm[1:])
973        ksearch.append(keyterm[1:])
974        ksearch.append(keyterm[1:])
975    elif keyterm.count("@") == 1 and keyterm.startswith("@") is True:
976        ksearch.append("{0}@protonmail.com".format(keyterm[1:]))
977        ksearch.append("{0}@protonmail.ch".format(keyterm[1:]))
978        ksearch.append("{0}@pm.me".format(keyterm[1:]))
979    elif keyterm.count("@") == 0:
980        ksearch.append("{0}@protonmail.com".format(keyterm))
981        ksearch.append("{0}@protonmail.ch".format(keyterm))
982        ksearch.append("{0}@pm.me".format(keyterm))
983    elif keyterm.count("@") == 2 and keyterm.startswith("@") is False:
984        uidlist = keyterm.split("@")
985        for uid in uidlist:
986            ksearch.append("{0}@protonmail.com".format(uid))
987            ksearch.append("{0}@protonmail.ch".format(uid))
988            ksearch.append("{0}@pm.me".format(uid))
989    elif keyterm.count("@") > 2:
990        uidlist = keyterm.split("@")
991        for uid in uidlist:
992            ksearch.append("{0}@protonmail.com".format(uid))
993            ksearch.append("{0}@protonmail.ch".format(uid))
994            ksearch.append("{0}@pm.me".format(uid))
995    else:
996        ksearch.append(keyterm)
997
998    for k in ksearch:
999        payload = {"op": "get", "search": k}
1000        try:
1001            r = requests.get(url, verify=True, params=payload)
1002            if r.ok is True:
1003                result = c.key_import(r.content)
1004            elif r.ok is False:
1005                result = r.content
1006        except Exception as e:
1007            result = None
1008
1009        if result is not None and hasattr(result, "considered") is False:
1010            print("{0} for {1}".format(result.decode(), k))
1011        elif result is not None and hasattr(result, "considered") is True:
1012            num_keys = len(result.imports)
1013            new_revs = result.new_revocations
1014            new_sigs = result.new_signatures
1015            new_subs = result.new_sub_keys
1016            new_uids = result.new_user_ids
1017            new_scrt = result.secret_imported
1018            nochange = result.unchanged
1019            print("""
1020    The total number of keys considered for import was:  {0}
1021
1022    With UIDs wholely or partially matching the following string:
1023
1024            {1}
1025
1026       Number of keys revoked:  {2}
1027     Number of new signatures:  {3}
1028        Number of new subkeys:  {4}
1029       Number of new user IDs:  {5}
1030    Number of new secret keys:  {6}
1031     Number of unchanged keys:  {7}
1032
1033    The key IDs for all considered keys were:
1034    """.format(num_keys, k, new_revs, new_sigs, new_subs, new_uids, new_scrt,
1035               nochange))
1036            for i in range(num_keys):
1037                print(result.imports[i].fpr)
1038            print("")
1039        elif result is None:
1040            print(e)
1041
1042 Both the above example,
1043 `pmkey-import.py <../examples/howto/pmkey-import.py>`__, and a version
1044 which prompts for an alternative GnuPG home directory,
1045 `pmkey-import-alt.py <../examples/howto/pmkey-import-alt.py>`__, are
1046 available with the other examples and are executable scripts.
1047
1048 Note that while the ProtonMail servers are based on the SKS servers,
1049 their server is related more to their API and is not feature complete by
1050 comparison to the servers in the SKS pool. One notable difference being
1051 that the ProtonMail server does not permit non ProtonMail users to
1052 update their own keys, which could be a vector for attacking ProtonMail
1053 users who may not receive a key\'s revocation if it had been
1054 compromised.
1055
1056 .. _import-hkp4py:
1057
1058 Importing with HKP for Python
1059 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1060
1061 Performing the same tasks with the `hkp4py
1062 module <https://github.com/Selfnet/hkp4py>`__ (available via PyPI) is
1063 not too much different, but does provide a number of options of benefit
1064 to end users. Not least of which being the ability to perform some
1065 checks on a key before importing it or not. For instance it may be the
1066 policy of a site or project to only import keys which have not been
1067 revoked. The hkp4py module permits such checks prior to the importing of
1068 the keys found.
1069
1070 .. code:: python
1071
1072    import gpg
1073    import hkp4py
1074    import sys
1075
1076    c = gpg.Context()
1077    server = hkp4py.KeyServer("hkps://hkps.pool.sks-keyservers.net")
1078    results = []
1079    keys = []
1080
1081    if len(sys.argv) > 2:
1082        pattern = " ".join(sys.argv[1:])
1083    elif len(sys.argv) == 2:
1084        pattern = sys.argv[1]
1085    else:
1086        pattern = input("Enter the pattern to search for keys or user IDs: ")
1087
1088
1089    if pattern is not None:
1090        try:
1091            key = server.search(hex(int(pattern, 16)))
1092            keyed = True
1093        except ValueError as ve:
1094            key = server.search(pattern)
1095            keyed = False
1096
1097        if key is not None:
1098            keys.append(key[0])
1099            if keyed is True:
1100                try:
1101                    fob = server.search(pattern)
1102                except:
1103                    fob = None
1104                if fob is not None:
1105                    keys.append(fob[0])
1106            else:
1107                pass
1108        else:
1109            pass
1110
1111        for logrus in pattern.split():
1112            try:
1113                key = server.search(hex(int(logrus, 16)))
1114                hexed = True
1115            except ValueError as ve:
1116                key = server.search(logrus)
1117                hexed = False
1118
1119            if key is not None:
1120                keys.append(key[0])
1121                if hexed is True:
1122                    try:
1123                        fob = server.search(logrus)
1124                    except:
1125                        fob = None
1126                    if fob is not None:
1127                        keys.append(fob[0])
1128                else:
1129                    pass
1130            else:
1131                pass
1132
1133
1134    if len(keys) > 0:
1135        for key in keys:
1136            import_result = c.key_import(key.key_blob)
1137            results.append(import_result)
1138
1139    for result in results:
1140        if result is not None and hasattr(result, "considered") is False:
1141            print(result)
1142        elif result is not None and hasattr(result, "considered") is True:
1143            num_keys = len(result.imports)
1144            new_revs = result.new_revocations
1145            new_sigs = result.new_signatures
1146            new_subs = result.new_sub_keys
1147            new_uids = result.new_user_ids
1148            new_scrt = result.secret_imported
1149            nochange = result.unchanged
1150            print("""
1151    The total number of keys considered for import was:  {0}
1152
1153       Number of keys revoked:  {1}
1154     Number of new signatures:  {2}
1155        Number of new subkeys:  {3}
1156       Number of new user IDs:  {4}
1157    Number of new secret keys:  {5}
1158     Number of unchanged keys:  {6}
1159
1160    The key IDs for all considered keys were:
1161    """.format(num_keys, new_revs, new_sigs, new_subs, new_uids, new_scrt,
1162               nochange))
1163            for i in range(num_keys):
1164                print(result.imports[i].fpr)
1165            print("")
1166        else:
1167            pass
1168
1169 Since the hkp4py module handles multiple keys just as effectively as one
1170 (``keys`` is a list of responses per matching key), the example above is
1171 able to do a little bit more with the returned data before anything is
1172 actually imported.
1173
1174 .. _import-protonmail-hkp4py:
1175
1176 Importing from ProtonMail with HKP for Python
1177 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1178
1179 Though this can provide certain benefits even when working with
1180 ProtonMail, the scope is somewhat constrained there due to the
1181 limitations of the ProtonMail keyserver.
1182
1183 For instance, searching the SKS keyserver pool for the term \"gnupg\"
1184 produces hundreds of results from any time the word appears in any part
1185 of a user ID. Performing the same search on the ProtonMail keyserver
1186 returns zero results, even though there are at least two test accounts
1187 which include it as part of the username.
1188
1189 The cause of this discrepancy is the deliberate configuration of that
1190 server by ProtonMail to require an exact match of the full email address
1191 of the ProtonMail user whose key is being requested. Presumably this is
1192 intended to reduce breaches of privacy of their users as an email
1193 address must already be known before a key for that address can be
1194 obtained.
1195
1196 #. Import from ProtonMail via HKP for Python Example no. 1
1197
1198    The following script is available with the rest of the examples under
1199    the somewhat less than original name, ``pmkey-import-hkp.py``.
1200
1201    .. code:: python
1202
1203       import gpg
1204       import hkp4py
1205       import os.path
1206       import sys
1207
1208       print("""
1209       This script searches the ProtonMail key server for the specified key and
1210       imports it.
1211
1212       Usage:  pmkey-import-hkp.py [search strings]
1213       """)
1214
1215       c = gpg.Context(armor=True)
1216       server = hkp4py.KeyServer("hkps://api.protonmail.ch")
1217       keyterms = []
1218       ksearch = []
1219       allkeys = []
1220       results = []
1221       paradox = []
1222       homeless = None
1223
1224       if len(sys.argv) > 2:
1225           keyterms = sys.argv[1:]
1226       elif len(sys.argv) == 2:
1227           keyterm = sys.argv[1]
1228           keyterms.append(keyterm)
1229       else:
1230           key_term = input("Enter the key ID, UID or search string: ")
1231           keyterms = key_term.split()
1232
1233       for keyterm in keyterms:
1234           if keyterm.count("@") == 2 and keyterm.startswith("@") is True:
1235               ksearch.append(keyterm[1:])
1236               ksearch.append(keyterm[1:])
1237               ksearch.append(keyterm[1:])
1238           elif keyterm.count("@") == 1 and keyterm.startswith("@") is True:
1239               ksearch.append("{0}@protonmail.com".format(keyterm[1:]))
1240               ksearch.append("{0}@protonmail.ch".format(keyterm[1:]))
1241               ksearch.append("{0}@pm.me".format(keyterm[1:]))
1242           elif keyterm.count("@") == 0:
1243               ksearch.append("{0}@protonmail.com".format(keyterm))
1244               ksearch.append("{0}@protonmail.ch".format(keyterm))
1245               ksearch.append("{0}@pm.me".format(keyterm))
1246           elif keyterm.count("@") == 2 and keyterm.startswith("@") is False:
1247               uidlist = keyterm.split("@")
1248               for uid in uidlist:
1249                   ksearch.append("{0}@protonmail.com".format(uid))
1250                   ksearch.append("{0}@protonmail.ch".format(uid))
1251                   ksearch.append("{0}@pm.me".format(uid))
1252           elif keyterm.count("@") > 2:
1253               uidlist = keyterm.split("@")
1254               for uid in uidlist:
1255                   ksearch.append("{0}@protonmail.com".format(uid))
1256                   ksearch.append("{0}@protonmail.ch".format(uid))
1257                   ksearch.append("{0}@pm.me".format(uid))
1258           else:
1259               ksearch.append(keyterm)
1260
1261       for k in ksearch:
1262           print("Checking for key for: {0}".format(k))
1263           try:
1264               keys = server.search(k)
1265               if isinstance(keys, list) is True:
1266                   for key in keys:
1267                       allkeys.append(key)
1268                       try:
1269                           import_result = c.key_import(key.key_blob)
1270                       except Exception as e:
1271                           import_result = c.key_import(key.key)
1272               else:
1273                   paradox.append(keys)
1274                   import_result = None
1275           except Exception as e:
1276               import_result = None
1277           results.append(import_result)
1278
1279       for result in results:
1280           if result is not None and hasattr(result, "considered") is False:
1281               print("{0} for {1}".format(result.decode(), k))
1282           elif result is not None and hasattr(result, "considered") is True:
1283               num_keys = len(result.imports)
1284               new_revs = result.new_revocations
1285               new_sigs = result.new_signatures
1286               new_subs = result.new_sub_keys
1287               new_uids = result.new_user_ids
1288               new_scrt = result.secret_imported
1289               nochange = result.unchanged
1290               print("""
1291       The total number of keys considered for import was:  {0}
1292
1293       With UIDs wholely or partially matching the following string:
1294
1295               {1}
1296
1297          Number of keys revoked:  {2}
1298        Number of new signatures:  {3}
1299           Number of new subkeys:  {4}
1300          Number of new user IDs:  {5}
1301       Number of new secret keys:  {6}
1302        Number of unchanged keys:  {7}
1303
1304       The key IDs for all considered keys were:
1305       """.format(num_keys, k, new_revs, new_sigs, new_subs, new_uids, new_scrt,
1306                  nochange))
1307               for i in range(num_keys):
1308                   print(result.imports[i].fpr)
1309               print("")
1310           elif result is None:
1311               pass
1312
1313 #. Import from ProtonMail via HKP for Python Example no. 2
1314
1315    Like its counterpart above, this script can also be found with the
1316    rest of the examples, by the name pmkey-import-hkp-alt.py.
1317
1318    With this script a modicum of effort has been made to treat anything
1319    passed as a ``homedir`` which either does not exist or which is not a
1320    directory, as also being a pssible user ID to check for. It\'s not
1321    guaranteed to pick up on all such cases, but it should cover most of
1322    them.
1323
1324    .. code:: python
1325
1326       import gpg
1327       import hkp4py
1328       import os.path
1329       import sys
1330
1331       print("""
1332       This script searches the ProtonMail key server for the specified key and
1333       imports it.  Optionally enables specifying a different GnuPG home directory.
1334
1335       Usage:  pmkey-import-hkp.py [homedir] [search string]
1336          or:  pmkey-import-hkp.py [search string]
1337       """)
1338
1339       c = gpg.Context(armor=True)
1340       server = hkp4py.KeyServer("hkps://api.protonmail.ch")
1341       keyterms = []
1342       ksearch = []
1343       allkeys = []
1344       results = []
1345       paradox = []
1346       homeless = None
1347
1348       if len(sys.argv) > 3:
1349           homedir = sys.argv[1]
1350           keyterms = sys.argv[2:]
1351       elif len(sys.argv) == 3:
1352           homedir = sys.argv[1]
1353           keyterm = sys.argv[2]
1354           keyterms.append(keyterm)
1355       elif len(sys.argv) == 2:
1356           homedir = ""
1357           keyterm = sys.argv[1]
1358           keyterms.append(keyterm)
1359       else:
1360           keyterm = input("Enter the key ID, UID or search string: ")
1361           homedir = input("Enter the GPG configuration directory path (optional): ")
1362           keyterms.append(keyterm)
1363
1364       if len(homedir) == 0:
1365           homedir = None
1366           homeless = False
1367
1368       if homedir is not None:
1369           if homedir.startswith("~"):
1370               if os.path.exists(os.path.expanduser(homedir)) is True:
1371                   if os.path.isdir(os.path.expanduser(homedir)) is True:
1372                       c.home_dir = os.path.realpath(os.path.expanduser(homedir))
1373                   else:
1374                       homeless = True
1375               else:
1376                   homeless = True
1377           elif os.path.exists(os.path.realpath(homedir)) is True:
1378               if os.path.isdir(os.path.realpath(homedir)) is True:
1379                   c.home_dir = os.path.realpath(homedir)
1380               else:
1381                   homeless = True
1382           else:
1383               homeless = True
1384
1385       # First check to see if the homedir really is a homedir and if not, treat it as
1386       # a search string.
1387       if homeless is True:
1388           keyterms.append(homedir)
1389           c.home_dir = None
1390       else:
1391           pass
1392
1393       for keyterm in keyterms:
1394           if keyterm.count("@") == 2 and keyterm.startswith("@") is True:
1395               ksearch.append(keyterm[1:])
1396               ksearch.append(keyterm[1:])
1397               ksearch.append(keyterm[1:])
1398           elif keyterm.count("@") == 1 and keyterm.startswith("@") is True:
1399               ksearch.append("{0}@protonmail.com".format(keyterm[1:]))
1400               ksearch.append("{0}@protonmail.ch".format(keyterm[1:]))
1401               ksearch.append("{0}@pm.me".format(keyterm[1:]))
1402           elif keyterm.count("@") == 0:
1403               ksearch.append("{0}@protonmail.com".format(keyterm))
1404               ksearch.append("{0}@protonmail.ch".format(keyterm))
1405               ksearch.append("{0}@pm.me".format(keyterm))
1406           elif keyterm.count("@") == 2 and keyterm.startswith("@") is False:
1407               uidlist = keyterm.split("@")
1408               for uid in uidlist:
1409                   ksearch.append("{0}@protonmail.com".format(uid))
1410                   ksearch.append("{0}@protonmail.ch".format(uid))
1411                   ksearch.append("{0}@pm.me".format(uid))
1412           elif keyterm.count("@") > 2:
1413               uidlist = keyterm.split("@")
1414               for uid in uidlist:
1415                   ksearch.append("{0}@protonmail.com".format(uid))
1416                   ksearch.append("{0}@protonmail.ch".format(uid))
1417                   ksearch.append("{0}@pm.me".format(uid))
1418           else:
1419               ksearch.append(keyterm)
1420
1421       for k in ksearch:
1422           print("Checking for key for: {0}".format(k))
1423           try:
1424               keys = server.search(k)
1425               if isinstance(keys, list) is True:
1426                   for key in keys:
1427                       allkeys.append(key)
1428                       try:
1429                           import_result = c.key_import(key.key_blob)
1430                       except Exception as e:
1431                           import_result = c.key_import(key.key)
1432               else:
1433                   paradox.append(keys)
1434                   import_result = None
1435           except Exception as e:
1436               import_result = None
1437           results.append(import_result)
1438
1439       for result in results:
1440           if result is not None and hasattr(result, "considered") is False:
1441               print("{0} for {1}".format(result.decode(), k))
1442           elif result is not None and hasattr(result, "considered") is True:
1443               num_keys = len(result.imports)
1444               new_revs = result.new_revocations
1445               new_sigs = result.new_signatures
1446               new_subs = result.new_sub_keys
1447               new_uids = result.new_user_ids
1448               new_scrt = result.secret_imported
1449               nochange = result.unchanged
1450               print("""
1451       The total number of keys considered for import was:  {0}
1452
1453       With UIDs wholely or partially matching the following string:
1454
1455               {1}
1456
1457          Number of keys revoked:  {2}
1458        Number of new signatures:  {3}
1459           Number of new subkeys:  {4}
1460          Number of new user IDs:  {5}
1461       Number of new secret keys:  {6}
1462        Number of unchanged keys:  {7}
1463
1464       The key IDs for all considered keys were:
1465       """.format(num_keys, k, new_revs, new_sigs, new_subs, new_uids, new_scrt,
1466                  nochange))
1467               for i in range(num_keys):
1468                   print(result.imports[i].fpr)
1469               print("")
1470           elif result is None:
1471               pass
1472
1473 .. _howto-export-key:
1474
1475 Exporting keys
1476 --------------
1477
1478 Exporting keys remains a reasonably simple task, but has been separated
1479 into three different functions for the OpenPGP cryptographic engine. Two
1480 of those functions are for exporting public keys and the third is for
1481 exporting secret keys.
1482
1483 .. _howto-export-public-key:
1484
1485 Exporting public keys
1486 ~~~~~~~~~~~~~~~~~~~~~
1487
1488 There are two methods of exporting public keys, both of which are very
1489 similar to the other. The default method, ``key_export()``, will export
1490 a public key or keys matching a specified pattern as normal. The
1491 alternative, the ``key_export_minimal()`` method, will do the same thing
1492 except producing a minimised output with extra signatures and third
1493 party signatures or certifications removed.
1494
1495 .. code:: python
1496
1497    import gpg
1498    import os.path
1499    import sys
1500
1501    print("""
1502    This script exports one or more public keys.
1503    """)
1504
1505    c = gpg.Context(armor=True)
1506
1507    if len(sys.argv) >= 4:
1508        keyfile = sys.argv[1]
1509        logrus = sys.argv[2]
1510        homedir = sys.argv[3]
1511    elif len(sys.argv) == 3:
1512        keyfile = sys.argv[1]
1513        logrus = sys.argv[2]
1514        homedir = input("Enter the GPG configuration directory path (optional): ")
1515    elif len(sys.argv) == 2:
1516        keyfile = sys.argv[1]
1517        logrus = input("Enter the UID matching the key(s) to export: ")
1518        homedir = input("Enter the GPG configuration directory path (optional): ")
1519    else:
1520        keyfile = input("Enter the path and filename to save the secret key to: ")
1521        logrus = input("Enter the UID matching the key(s) to export: ")
1522        homedir = input("Enter the GPG configuration directory path (optional): ")
1523
1524    if homedir.startswith("~"):
1525        if os.path.exists(os.path.expanduser(homedir)) is True:
1526            c.home_dir = os.path.expanduser(homedir)
1527        else:
1528            pass
1529    elif os.path.exists(homedir) is True:
1530        c.home_dir = homedir
1531    else:
1532        pass
1533
1534    try:
1535        result = c.key_export(pattern=logrus)
1536    except:
1537        result = c.key_export(pattern=None)
1538
1539    if result is not None:
1540        with open(keyfile, "wb") as f:
1541            f.write(result)
1542    else:
1543        pass
1544
1545 It should be noted that the result will only return ``None`` when a
1546 search pattern has been entered, but has not matched any keys. When the
1547 search pattern itself is set to ``None`` this triggers the exporting of
1548 the entire public keybox.
1549
1550 .. code:: python
1551
1552    import gpg
1553    import os.path
1554    import sys
1555
1556    print("""
1557    This script exports one or more public keys in minimised form.
1558    """)
1559
1560    c = gpg.Context(armor=True)
1561
1562    if len(sys.argv) >= 4:
1563        keyfile = sys.argv[1]
1564        logrus = sys.argv[2]
1565        homedir = sys.argv[3]
1566    elif len(sys.argv) == 3:
1567        keyfile = sys.argv[1]
1568        logrus = sys.argv[2]
1569        homedir = input("Enter the GPG configuration directory path (optional): ")
1570    elif len(sys.argv) == 2:
1571        keyfile = sys.argv[1]
1572        logrus = input("Enter the UID matching the key(s) to export: ")
1573        homedir = input("Enter the GPG configuration directory path (optional): ")
1574    else:
1575        keyfile = input("Enter the path and filename to save the secret key to: ")
1576        logrus = input("Enter the UID matching the key(s) to export: ")
1577        homedir = input("Enter the GPG configuration directory path (optional): ")
1578
1579    if homedir.startswith("~"):
1580        if os.path.exists(os.path.expanduser(homedir)) is True:
1581            c.home_dir = os.path.expanduser(homedir)
1582        else:
1583            pass
1584    elif os.path.exists(homedir) is True:
1585        c.home_dir = homedir
1586    else:
1587        pass
1588
1589    try:
1590        result = c.key_export_minimal(pattern=logrus)
1591    except:
1592        result = c.key_export_minimal(pattern=None)
1593
1594    if result is not None:
1595        with open(keyfile, "wb") as f:
1596            f.write(result)
1597    else:
1598        pass
1599
1600 .. _howto-export-secret-key:
1601
1602 Exporting secret keys
1603 ~~~~~~~~~~~~~~~~~~~~~
1604
1605 Exporting secret keys is, functionally, very similar to exporting public
1606 keys; save for the invocation of ``pinentry`` via ``gpg-agent`` in order
1607 to securely enter the key\'s passphrase and authorise the export.
1608
1609 The following example exports the secret key to a file which is then set
1610 with the same permissions as the output files created by the command
1611 line secret key export options.
1612
1613 .. code:: python
1614
1615    import gpg
1616    import os
1617    import os.path
1618    import sys
1619
1620    print("""
1621    This script exports one or more secret keys.
1622
1623    The gpg-agent and pinentry are invoked to authorise the export.
1624    """)
1625
1626    c = gpg.Context(armor=True)
1627
1628    if len(sys.argv) >= 4:
1629        keyfile = sys.argv[1]
1630        logrus = sys.argv[2]
1631        homedir = sys.argv[3]
1632    elif len(sys.argv) == 3:
1633        keyfile = sys.argv[1]
1634        logrus = sys.argv[2]
1635        homedir = input("Enter the GPG configuration directory path (optional): ")
1636    elif len(sys.argv) == 2:
1637        keyfile = sys.argv[1]
1638        logrus = input("Enter the UID matching the secret key(s) to export: ")
1639        homedir = input("Enter the GPG configuration directory path (optional): ")
1640    else:
1641        keyfile = input("Enter the path and filename to save the secret key to: ")
1642        logrus = input("Enter the UID matching the secret key(s) to export: ")
1643        homedir = input("Enter the GPG configuration directory path (optional): ")
1644
1645    if len(homedir) == 0:
1646        homedir = None
1647    elif homedir.startswith("~"):
1648        userdir = os.path.expanduser(homedir)
1649        if os.path.exists(userdir) is True:
1650            homedir = os.path.realpath(userdir)
1651        else:
1652            homedir = None
1653    else:
1654        homedir = os.path.realpath(homedir)
1655
1656    if os.path.exists(homedir) is False:
1657        homedir = None
1658    else:
1659        if os.path.isdir(homedir) is False:
1660            homedir = None
1661        else:
1662            pass
1663
1664    if homedir is not None:
1665        c.home_dir = homedir
1666    else:
1667        pass
1668
1669    try:
1670        result = c.key_export_secret(pattern=logrus)
1671    except:
1672        result = c.key_export_secret(pattern=None)
1673
1674    if result is not None:
1675        with open(keyfile, "wb") as f:
1676            f.write(result)
1677        os.chmod(keyfile, 0o600)
1678    else:
1679        pass
1680
1681 Alternatively the approach of the following script can be used. This
1682 longer example saves the exported secret key(s) in files in the GnuPG
1683 home directory, in addition to setting the file permissions as only
1684 readable and writable by the user. It also exports the secret key(s)
1685 twice in order to output both GPG binary (``.gpg``) and ASCII armoured
1686 (``.asc``) files.
1687
1688 .. code:: python
1689
1690    import gpg
1691    import os
1692    import os.path
1693    import subprocess
1694    import sys
1695
1696    print("""
1697    This script exports one or more secret keys as both ASCII armored and binary
1698    file formats, saved in files within the user's GPG home directory.
1699
1700    The gpg-agent and pinentry are invoked to authorise the export.
1701    """)
1702
1703    if sys.platform == "win32":
1704        gpgconfcmd = "gpgconf.exe --list-dirs homedir"
1705    else:
1706        gpgconfcmd = "gpgconf --list-dirs homedir"
1707
1708    a = gpg.Context(armor=True)
1709    b = gpg.Context()
1710    c = gpg.Context()
1711
1712    if len(sys.argv) >= 4:
1713        keyfile = sys.argv[1]
1714        logrus = sys.argv[2]
1715        homedir = sys.argv[3]
1716    elif len(sys.argv) == 3:
1717        keyfile = sys.argv[1]
1718        logrus = sys.argv[2]
1719        homedir = input("Enter the GPG configuration directory path (optional): ")
1720    elif len(sys.argv) == 2:
1721        keyfile = sys.argv[1]
1722        logrus = input("Enter the UID matching the secret key(s) to export: ")
1723        homedir = input("Enter the GPG configuration directory path (optional): ")
1724    else:
1725        keyfile = input("Enter the filename to save the secret key to: ")
1726        logrus = input("Enter the UID matching the secret key(s) to export: ")
1727        homedir = input("Enter the GPG configuration directory path (optional): ")
1728
1729    if len(homedir) == 0:
1730        homedir = None
1731    elif homedir.startswith("~"):
1732        userdir = os.path.expanduser(homedir)
1733        if os.path.exists(userdir) is True:
1734            homedir = os.path.realpath(userdir)
1735        else:
1736            homedir = None
1737    else:
1738        homedir = os.path.realpath(homedir)
1739
1740    if os.path.exists(homedir) is False:
1741        homedir = None
1742    else:
1743        if os.path.isdir(homedir) is False:
1744            homedir = None
1745        else:
1746            pass
1747
1748    if homedir is not None:
1749        c.home_dir = homedir
1750    else:
1751        pass
1752
1753    if c.home_dir is not None:
1754        if c.home_dir.endswith("/"):
1755            gpgfile = "{0}{1}.gpg".format(c.home_dir, keyfile)
1756            ascfile = "{0}{1}.asc".format(c.home_dir, keyfile)
1757        else:
1758            gpgfile = "{0}/{1}.gpg".format(c.home_dir, keyfile)
1759            ascfile = "{0}/{1}.asc".format(c.home_dir, keyfile)
1760    else:
1761        if os.path.exists(os.environ["GNUPGHOME"]) is True:
1762            hd = os.environ["GNUPGHOME"]
1763        else:
1764            try:
1765                hd = subprocess.getoutput(gpgconfcmd)
1766            except:
1767                process = subprocess.Popen(gpgconfcmd.split(),
1768                                           stdout=subprocess.PIPE)
1769                procom = process.communicate()
1770                if sys.version_info[0] == 2:
1771                    hd = procom[0].strip()
1772                else:
1773                    hd = procom[0].decode().strip()
1774        gpgfile = "{0}/{1}.gpg".format(hd, keyfile)
1775        ascfile = "{0}/{1}.asc".format(hd, keyfile)
1776
1777    try:
1778        a_result = a.key_export_secret(pattern=logrus)
1779        b_result = b.key_export_secret(pattern=logrus)
1780    except:
1781        a_result = a.key_export_secret(pattern=None)
1782        b_result = b.key_export_secret(pattern=None)
1783
1784    if a_result is not None:
1785        with open(ascfile, "wb") as f:
1786            f.write(a_result)
1787        os.chmod(ascfile, 0o600)
1788    else:
1789        pass
1790
1791    if b_result is not None:
1792        with open(gpgfile, "wb") as f:
1793            f.write(b_result)
1794        os.chmod(gpgfile, 0o600)
1795    else:
1796        pass
1797
1798 .. _howto-send-public-key:
1799
1800 Sending public keys to the SKS Keyservers
1801 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1802
1803 As with the previous section on importing keys, the ``hkp4py`` module
1804 adds another option with exporting keys in order to send them to the
1805 public keyservers.
1806
1807 The following example demonstrates how this may be done.
1808
1809 .. code:: python
1810
1811    import gpg
1812    import hkp4py
1813    import os.path
1814    import sys
1815
1816    print("""
1817    This script sends one or more public keys to the SKS keyservers and is
1818    essentially a slight variation on the export-key.py script.
1819    """)
1820
1821    c = gpg.Context(armor=True)
1822    server = hkp4py.KeyServer("hkps://hkps.pool.sks-keyservers.net")
1823
1824    if len(sys.argv) > 2:
1825        logrus = " ".join(sys.argv[1:])
1826    elif len(sys.argv) == 2:
1827        logrus = sys.argv[1]
1828    else:
1829        logrus = input("Enter the UID matching the key(s) to send: ")
1830
1831    if len(logrus) > 0:
1832        try:
1833            export_result = c.key_export(pattern=logrus)
1834        except Exception as e:
1835            print(e)
1836            export_result = None
1837    else:
1838        export_result = c.key_export(pattern=None)
1839
1840    if export_result is not None:
1841        try:
1842            try:
1843                send_result = server.add(export_result)
1844            except:
1845                send_result = server.add(export_result.decode())
1846            if send_result is not None:
1847                print(send_result)
1848            else:
1849                pass
1850        except Exception as e:
1851            print(e)
1852    else:
1853        pass
1854
1855 An expanded version of this script with additional functions for
1856 specifying an alternative homedir location is in the examples directory
1857 as ``send-key-to-keyserver.py``.
1858
1859 The ``hkp4py`` module appears to handle both string and byte literal
1860 text data equally well, but the GPGME bindings deal primarily with byte
1861 literal data only and so this script sends in that format first, then
1862 tries the string literal form.
1863
1864 .. _howto-the-basics:
1865
1866 Basic Functions
1867 ===============
1868
1869 The most frequently called features of any cryptographic library will be
1870 the most fundamental tasks for encryption software. In this section we
1871 will look at how to programmatically encrypt data, decrypt it, sign it
1872 and verify signatures.
1873
1874 .. _howto-basic-encryption:
1875
1876 Encryption
1877 ----------
1878
1879 Encrypting is very straight forward. In the first example below the
1880 message, ``text``, is encrypted to a single recipient\'s key. In the
1881 second example the message will be encrypted to multiple recipients.
1882
1883 .. _howto-basic-encryption-single:
1884
1885 Encrypting to one key
1886 ~~~~~~~~~~~~~~~~~~~~~
1887
1888 Once the the Context is set the main issues with encrypting data is
1889 essentially reduced to key selection and the keyword arguments specified
1890 in the ``gpg.Context().encrypt()`` method.
1891
1892 Those keyword arguments are: ``recipients``, a list of keys encrypted to
1893 (covered in greater detail in the following section); ``sign``, whether
1894 or not to sign the plaintext data, see subsequent sections on signing
1895 and verifying signatures below (defaults to ``True``); ``sink``, to
1896 write results or partial results to a secure sink instead of returning
1897 it (defaults to ``None``); ``passphrase``, only used when utilising
1898 symmetric encryption (defaults to ``None``); ``always_trust``, used to
1899 override the trust model settings for recipient keys (defaults to
1900 ``False``); ``add_encrypt_to``, utilises any preconfigured
1901 ``encrypt-to`` or ``default-key`` settings in the user\'s ``gpg.conf``
1902 file (defaults to ``False``); ``prepare``, prepare for encryption
1903 (defaults to ``False``); ``expect_sign``, prepare for signing (defaults
1904 to ``False``); ``compress``, compresses the plaintext prior to
1905 encryption (defaults to ``True``).
1906
1907 .. code:: python
1908
1909    import gpg
1910
1911    a_key = "0x12345678DEADBEEF"
1912    text = b"""Some text to test with.
1913
1914    Since the text in this case must be bytes, it is most likely that
1915    the input form will be a separate file which is opened with "rb"
1916    as this is the simplest method of obtaining the correct data format.
1917    """
1918
1919    c = gpg.Context(armor=True)
1920    rkey = list(c.keylist(pattern=a_key, secret=False))
1921    ciphertext, result, sign_result = c.encrypt(text, recipients=rkey, sign=False)
1922
1923    with open("secret_plans.txt.asc", "wb") as afile:
1924        afile.write(ciphertext)
1925
1926 Though this is even more likely to be used like this; with the plaintext
1927 input read from a file, the recipient keys used for encryption
1928 regardless of key trust status and the encrypted output also encrypted
1929 to any preconfigured keys set in the ``gpg.conf`` file:
1930
1931 .. code:: python
1932
1933    import gpg
1934
1935    a_key = "0x12345678DEADBEEF"
1936
1937    with open("secret_plans.txt", "rb") as afile:
1938        text = afile.read()
1939
1940    c = gpg.Context(armor=True)
1941    rkey = list(c.keylist(pattern=a_key, secret=False))
1942    ciphertext, result, sign_result = c.encrypt(text, recipients=rkey, sign=True,
1943                                                always_trust=True,
1944                                                add_encrypt_to=True)
1945
1946    with open("secret_plans.txt.asc", "wb") as afile:
1947        afile.write(ciphertext)
1948
1949 If the ``recipients`` parameter is empty then the plaintext is encrypted
1950 symmetrically. If no ``passphrase`` is supplied as a parameter or via a
1951 callback registered with the ``Context()`` then an out-of-band prompt
1952 for the passphrase via pinentry will be invoked.
1953
1954 .. _howto-basic-encryption-multiple:
1955
1956 Encrypting to multiple keys
1957 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1958
1959 Encrypting to multiple keys essentially just expands upon the key
1960 selection process and the recipients from the previous examples.
1961
1962 The following example encrypts a message (``text``) to everyone with an
1963 email address on the ``gnupg.org`` domain, [4]_ but does *not* encrypt
1964 to a default key or other key which is configured to normally encrypt
1965 to.
1966
1967 .. code:: python
1968
1969    import gpg
1970
1971    text = b"""Oh look, another test message.
1972
1973    The same rules apply as with the previous example and more likely
1974    than not, the message will actually be drawn from reading the
1975    contents of a file or, maybe, from entering data at an input()
1976    prompt.
1977
1978    Since the text in this case must be bytes, it is most likely that
1979    the input form will be a separate file which is opened with "rb"
1980    as this is the simplest method of obtaining the correct data
1981    format.
1982    """
1983
1984    c = gpg.Context(armor=True)
1985    rpattern = list(c.keylist(pattern="@gnupg.org", secret=False))
1986    logrus = []
1987
1988    for i in range(len(rpattern)):
1989        if rpattern[i].can_encrypt == 1:
1990            logrus.append(rpattern[i])
1991
1992    ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
1993                                                sign=False, always_trust=True)
1994
1995    with open("secret_plans.txt.asc", "wb") as afile:
1996        afile.write(ciphertext)
1997
1998 All it would take to change the above example to sign the message and
1999 also encrypt the message to any configured default keys would be to
2000 change the ``c.encrypt`` line to this:
2001
2002 .. code:: python
2003
2004    ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
2005                                                always_trust=True,
2006                                                add_encrypt_to=True)
2007
2008 The only keyword arguments requiring modification are those for which
2009 the default values are changing. The default value of ``sign`` is
2010 ``True``, the default of ``always_trust`` is ``False``, the default of
2011 ``add_encrypt_to`` is ``False``.
2012
2013 If ``always_trust`` is not set to ``True`` and any of the recipient keys
2014 are not trusted (e.g. not signed or locally signed) then the encryption
2015 will raise an error. It is possible to mitigate this somewhat with
2016 something more like this:
2017
2018 .. code:: python
2019
2020    import gpg
2021
2022    with open("secret_plans.txt.asc", "rb") as afile:
2023        text = afile.read()
2024
2025    c = gpg.Context(armor=True)
2026    rpattern = list(c.keylist(pattern="@gnupg.org", secret=False))
2027    logrus = []
2028
2029    for i in range(len(rpattern)):
2030        if rpattern[i].can_encrypt == 1:
2031            logrus.append(rpattern[i])
2032
2033        try:
2034            ciphertext, result, sign_result = c.encrypt(text, recipients=logrus,
2035                                                        add_encrypt_to=True)
2036        except gpg.errors.InvalidRecipients as e:
2037            for i in range(len(e.recipients)):
2038                for n in range(len(logrus)):
2039                    if logrus[n].fpr == e.recipients[i].fpr:
2040                        logrus.remove(logrus[n])
2041                    else:
2042                        pass
2043            try:
2044                ciphertext, result, sign_result = c.encrypt(text,
2045                                                            recipients=logrus,
2046                                                            add_encrypt_to=True)
2047                with open("secret_plans.txt.asc", "wb") as afile:
2048                    afile.write(ciphertext)
2049            except:
2050                pass
2051
2052 This will attempt to encrypt to all the keys searched for, then remove
2053 invalid recipients if it fails and try again.
2054
2055 .. _howto-basic-decryption:
2056
2057 Decryption
2058 ----------
2059
2060 Decrypting something encrypted to a key in one\'s secret keyring is
2061 fairly straight forward.
2062
2063 In this example code, however, preconfiguring either ``gpg.Context()``
2064 or ``gpg.core.Context()`` as ``c`` is unnecessary because there is no
2065 need to modify the Context prior to conducting the decryption and since
2066 the Context is only used once, setting it to ``c`` simply adds lines for
2067 no gain.
2068
2069 .. code:: python
2070
2071    import gpg
2072
2073    ciphertext = input("Enter path and filename of encrypted file: ")
2074    newfile = input("Enter path and filename of file to save decrypted data to: ")
2075
2076    with open(ciphertext, "rb") as cfile:
2077        try:
2078            plaintext, result, verify_result = gpg.Context().decrypt(cfile)
2079        except gpg.errors.GPGMEError as e:
2080            plaintext = None
2081            print(e)
2082
2083    if plaintext is not None:
2084        with open(newfile, "wb") as nfile:
2085            nfile.write(plaintext)
2086        else:
2087            pass
2088
2089 The data available in ``plaintext`` in this example is the decrypted
2090 content as a byte object, the recipient key IDs and algorithms in
2091 ``result`` and the results of verifying any signatures of the data in
2092 ``verify_result``.
2093
2094 If ``gpg.Context().decrypt(cfile, verify=False)`` is called instead,
2095 then ``verify_result`` will be returned as ``None`` and the rest remains
2096 as described here.
2097
2098 .. _howto-basic-signing:
2099
2100 Signing text and files
2101 ----------------------
2102
2103 The following sections demonstrate how to specify keys to sign with.
2104
2105 .. _howto-basic-signing-signers:
2106
2107 Signing key selection
2108 ~~~~~~~~~~~~~~~~~~~~~
2109
2110 By default GPGME and the Python bindings will use the default key
2111 configured for the user invoking the GPGME API. If there is no default
2112 key specified and there is more than one secret key available it may be
2113 necessary to specify the key or keys with which to sign messages and
2114 files.
2115
2116 .. code:: python
2117
2118    import gpg
2119
2120    logrus = input("Enter the email address or string to match signing keys to: ")
2121    hancock = gpg.Context().keylist(pattern=logrus, secret=True)
2122    sig_src = list(hancock)
2123
2124 The signing examples in the following sections include the explicitly
2125 designated ``signers`` parameter in two of the five examples; once where
2126 the resulting signature would be ASCII armoured and once where it would
2127 not be armoured.
2128
2129 While it would be possible to enter a key ID or fingerprint here to
2130 match a specific key, it is not possible to enter two fingerprints and
2131 match two keys since the patten expects a string, bytes or None and not
2132 a list. A string with two fingerprints won\'t match any single key.
2133
2134 .. _howto-basic-signing-normal:
2135
2136 Normal or default signing messages or files
2137 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2138
2139 The normal or default signing process is essentially the same as is most
2140 often invoked when also encrypting a message or file. So when the
2141 encryption component is not utilised, the result is to produce an
2142 encoded and signed output which may or may not be ASCII armoured and
2143 which may or may not also be compressed.
2144
2145 By default compression will be used unless GnuPG detects that the
2146 plaintext is already compressed. ASCII armouring will be determined
2147 according to the value of ``gpg.Context().armor``.
2148
2149 The compression algorithm is selected in much the same way as the
2150 symmetric encryption algorithm or the hash digest algorithm is when
2151 multiple keys are involved; from the preferences saved into the key
2152 itself or by comparison with the preferences with all other keys
2153 involved.
2154
2155 .. code:: python
2156
2157    import gpg
2158
2159    text0 = """Declaration of ... something.
2160
2161    """
2162    text = text0.encode()
2163
2164    c = gpg.Context(armor=True, signers=sig_src)
2165    signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.NORMAL)
2166
2167    with open("/path/to/statement.txt.asc", "w") as afile:
2168        afile.write(signed_data.decode())
2169
2170 Though everything in this example is accurate, it is more likely that
2171 reading the input data from another file and writing the result to a new
2172 file will be performed more like the way it is done in the next example.
2173 Even if the output format is ASCII armoured.
2174
2175 .. code:: python
2176
2177    import gpg
2178
2179    with open("/path/to/statement.txt", "rb") as tfile:
2180        text = tfile.read()
2181
2182    c = gpg.Context()
2183    signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.NORMAL)
2184
2185    with open("/path/to/statement.txt.sig", "wb") as afile:
2186        afile.write(signed_data)
2187
2188 .. _howto-basic-signing-detached:
2189
2190 Detached signing messages and files
2191 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2192
2193 Detached signatures will often be needed in programmatic uses of GPGME,
2194 either for signing files (e.g. tarballs of code releases) or as a
2195 component of message signing (e.g. PGP/MIME encoded email).
2196
2197 .. code:: python
2198
2199    import gpg
2200
2201    text0 = """Declaration of ... something.
2202
2203    """
2204    text = text0.encode()
2205
2206    c = gpg.Context(armor=True)
2207    signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.DETACH)
2208
2209    with open("/path/to/statement.txt.asc", "w") as afile:
2210        afile.write(signed_data.decode())
2211
2212 As with normal signatures, detached signatures are best handled as byte
2213 literals, even when the output is ASCII armoured.
2214
2215 .. code:: python
2216
2217    import gpg
2218
2219    with open("/path/to/statement.txt", "rb") as tfile:
2220        text = tfile.read()
2221
2222    c = gpg.Context(signers=sig_src)
2223    signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.DETACH)
2224
2225    with open("/path/to/statement.txt.sig", "wb") as afile:
2226        afile.write(signed_data)
2227
2228 .. _howto-basic-signing-clear:
2229
2230 Clearsigning messages or text
2231 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2232
2233 Though PGP/in-line messages are no longer encouraged in favour of
2234 PGP/MIME, there is still sometimes value in utilising in-line
2235 signatures. This is where clear-signed messages or text is of value.
2236
2237 .. code:: python
2238
2239    import gpg
2240
2241    text0 = """Declaration of ... something.
2242
2243    """
2244    text = text0.encode()
2245
2246    c = gpg.Context()
2247    signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.CLEAR)
2248
2249    with open("/path/to/statement.txt.asc", "w") as afile:
2250        afile.write(signed_data.decode())
2251
2252 In spite of the appearance of a clear-signed message, the data handled
2253 by GPGME in signing it must still be byte literals.
2254
2255 .. code:: python
2256
2257    import gpg
2258
2259    with open("/path/to/statement.txt", "rb") as tfile:
2260        text = tfile.read()
2261
2262    c = gpg.Context()
2263    signed_data, result = c.sign(text, mode=gpg.constants.sig.mode.CLEAR)
2264
2265    with open("/path/to/statement.txt.asc", "wb") as afile:
2266        afile.write(signed_data)
2267
2268 .. _howto-basic-verification:
2269
2270 Signature verification
2271 ----------------------
2272
2273 Essentially there are two principal methods of verification of a
2274 signature. The first of these is for use with the normal or default
2275 signing method and for clear-signed messages. The second is for use with
2276 files and data with detached signatures.
2277
2278 The following example is intended for use with the default signing
2279 method where the file was not ASCII armoured:
2280
2281 .. code:: python
2282
2283    import gpg
2284    import time
2285
2286    filename = "statement.txt"
2287    gpg_file = "statement.txt.gpg"
2288
2289    c = gpg.Context()
2290
2291    try:
2292        data, result = c.verify(open(gpg_file))
2293        verified = True
2294    except gpg.errors.BadSignatures as e:
2295        verified = False
2296        print(e)
2297
2298    if verified is True:
2299        for i in range(len(result.signatures)):
2300            sign = result.signatures[i]
2301            print("""Good signature from:
2302    {0}
2303    with key {1}
2304    made at {2}
2305    """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
2306               time.ctime(sign.timestamp)))
2307    else:
2308        pass
2309
2310 Whereas this next example, which is almost identical would work with
2311 normal ASCII armoured files and with clear-signed files:
2312
2313 .. code:: python
2314
2315    import gpg
2316    import time
2317
2318    filename = "statement.txt"
2319    asc_file = "statement.txt.asc"
2320
2321    c = gpg.Context()
2322
2323    try:
2324        data, result = c.verify(open(asc_file))
2325        verified = True
2326    except gpg.errors.BadSignatures as e:
2327        verified = False
2328        print(e)
2329
2330    if verified is True:
2331        for i in range(len(result.signatures)):
2332            sign = result.signatures[i]
2333            print("""Good signature from:
2334    {0}
2335    with key {1}
2336    made at {2}
2337    """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
2338               time.ctime(sign.timestamp)))
2339    else:
2340        pass
2341
2342 In both of the previous examples it is also possible to compare the
2343 original data that was signed against the signed data in ``data`` to see
2344 if it matches with something like this:
2345
2346 .. code:: python
2347
2348    with open(filename, "rb") as afile:
2349        text = afile.read()
2350
2351    if text == data:
2352        print("Good signature.")
2353    else:
2354        pass
2355
2356 The following two examples, however, deal with detached signatures. With
2357 his method of verification the data that was signed does not get
2358 returned since it is already being explicitly referenced in the first
2359 argument of ``c.verify``. So ``data`` is ``None`` and only the
2360 information in ``result`` is available.
2361
2362 .. code:: python
2363
2364    import gpg
2365    import time
2366
2367    filename = "statement.txt"
2368    sig_file = "statement.txt.sig"
2369
2370    c = gpg.Context()
2371
2372    try:
2373        data, result = c.verify(open(filename), open(sig_file))
2374        verified = True
2375    except gpg.errors.BadSignatures as e:
2376        verified = False
2377        print(e)
2378
2379    if verified is True:
2380        for i in range(len(result.signatures)):
2381            sign = result.signatures[i]
2382            print("""Good signature from:
2383    {0}
2384    with key {1}
2385    made at {2}
2386    """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
2387               time.ctime(sign.timestamp)))
2388    else:
2389        pass
2390
2391 .. code:: python
2392
2393    import gpg
2394    import time
2395
2396    filename = "statement.txt"
2397    asc_file = "statement.txt.asc"
2398
2399    c = gpg.Context()
2400
2401    try:
2402        data, result = c.verify(open(filename), open(asc_file))
2403        verified = True
2404    except gpg.errors.BadSignatures as e:
2405        verified = False
2406        print(e)
2407
2408    if verified is True:
2409        for i in range(len(result.signatures)):
2410            sign = result.signatures[i]
2411            print("""Good signature from:
2412    {0}
2413    with key {1}
2414    made at {2}
2415    """.format(c.get_key(sign.fpr).uids[0].uid, sign.fpr,
2416               time.ctime(sign.timestamp)))
2417    else:
2418        pass
2419
2420 .. _key-generation:
2421
2422 Creating keys and subkeys
2423 =========================
2424
2425 The one thing, aside from GnuPG itself, that GPGME depends on, of
2426 course, is the keys themselves. So it is necessary to be able to
2427 generate them and modify them by adding subkeys, revoking or disabling
2428 them, sometimes deleting them and doing the same for user IDs.
2429
2430 In the following examples a key will be created for the world\'s
2431 greatest secret agent, Danger Mouse. Since Danger Mouse is a secret
2432 agent he needs to be able to protect information to ``SECRET`` level
2433 clearance, so his keys will be 3072-bit keys.
2434
2435 The pre-configured ``gpg.conf`` file which sets cipher, digest and other
2436 preferences contains the following configuration parameters:
2437
2438 .. code:: conf
2439
2440    expert
2441    allow-freeform-uid
2442    allow-secret-key-import
2443    trust-model tofu+pgp
2444    tofu-default-policy unknown
2445    enable-large-rsa
2446    enable-dsa2
2447    cert-digest-algo SHA512
2448    default-preference-list TWOFISH CAMELLIA256 AES256 CAMELLIA192 AES192 CAMELLIA128 AES BLOWFISH IDEA CAST5 3DES SHA512 SHA384 SHA256 SHA224 RIPEMD160 SHA1 ZLIB BZIP2 ZIP Uncompressed
2449    personal-cipher-preferences TWOFISH CAMELLIA256 AES256 CAMELLIA192 AES192 CAMELLIA128 AES BLOWFISH IDEA CAST5 3DES
2450    personal-digest-preferences SHA512 SHA384 SHA256 SHA224 RIPEMD160 SHA1
2451    personal-compress-preferences ZLIB BZIP2 ZIP Uncompressed
2452
2453 .. _keygen-primary:
2454
2455 Primary key
2456 -----------
2457
2458 Generating a primary key uses the ``create_key`` method in a Context. It
2459 contains multiple arguments and keyword arguments, including:
2460 ``userid``, ``algorithm``, ``expires_in``, ``expires``, ``sign``,
2461 ``encrypt``, ``certify``, ``authenticate``, ``passphrase`` and
2462 ``force``. The defaults for all of those except ``userid``,
2463 ``algorithm``, ``expires_in``, ``expires`` and ``passphrase`` is
2464 ``False``. The defaults for ``algorithm`` and ``passphrase`` is
2465 ``None``. The default for ``expires_in`` is ``0``. The default for
2466 ``expires`` is ``True``. There is no default for ``userid``.
2467
2468 If ``passphrase`` is left as ``None`` then the key will not be generated
2469 with a passphrase, if ``passphrase`` is set to a string then that will
2470 be the passphrase and if ``passphrase`` is set to ``True`` then
2471 gpg-agent will launch pinentry to prompt for a passphrase. For the sake
2472 of convenience, these examples will keep ``passphrase`` set to ``None``.
2473
2474 .. code:: python
2475
2476    import gpg
2477
2478    c = gpg.Context()
2479
2480    c.home_dir = "~/.gnupg-dm"
2481    userid = "Danger Mouse <dm@secret.example.net>"
2482
2483    dmkey = c.create_key(userid, algorithm="rsa3072", expires_in=31536000,
2484                         sign=True, certify=True)
2485
2486 One thing to note here is the use of setting the ``c.home_dir``
2487 parameter. This enables generating the key or keys in a different
2488 location. In this case to keep the new key data created for this example
2489 in a separate location rather than adding it to existing and active key
2490 store data. As with the default directory, ``~/.gnupg``, any temporary
2491 or separate directory needs the permissions set to only permit access by
2492 the directory owner. On posix systems this means setting the directory
2493 permissions to 700.
2494
2495 The ``temp-homedir-config.py`` script in the HOWTO examples directory
2496 will create an alternative homedir with these configuration options
2497 already set and the correct directory and file permissions.
2498
2499 The successful generation of the key can be confirmed via the returned
2500 ``GenkeyResult`` object, which includes the following data:
2501
2502 .. code:: python
2503
2504    print("""
2505     Fingerprint:  {0}
2506     Primary Key:  {1}
2507      Public Key:  {2}
2508      Secret Key:  {3}
2509     Sub Key:  {4}
2510    User IDs:  {5}
2511    """.format(dmkey.fpr, dmkey.primary, dmkey.pubkey, dmkey.seckey, dmkey.sub,
2512               dmkey.uid))
2513
2514 Alternatively the information can be confirmed using the command line
2515 program:
2516
2517 .. code:: shell
2518
2519    bash-4.4$ gpg --homedir ~/.gnupg-dm -K
2520    ~/.gnupg-dm/pubring.kbx
2521    ----------------------
2522    sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
2523      177B7C25DB99745EE2EE13ED026D2F19E99E63AA
2524    uid           [ultimate] Danger Mouse <dm@secret.example.net>
2525
2526    bash-4.4$
2527
2528 As with generating keys manually, to preconfigure expanded preferences
2529 for the cipher, digest and compression algorithms, the ``gpg.conf`` file
2530 must contain those details in the home directory in which the new key is
2531 being generated. I used a cut down version of my own ``gpg.conf`` file
2532 in order to be able to generate this:
2533
2534 .. code:: shell
2535
2536    bash-4.4$ gpg --homedir ~/.gnupg-dm --edit-key 177B7C25DB99745EE2EE13ED026D2F19E99E63AA showpref quit
2537    Secret key is available.
2538
2539    sec  rsa3072/026D2F19E99E63AA
2540         created: 2018-03-15  expires: 2019-03-15  usage: SC
2541         trust: ultimate      validity: ultimate
2542    [ultimate] (1). Danger Mouse <dm@secret.example.net>
2543
2544    [ultimate] (1). Danger Mouse <dm@secret.example.net>
2545         Cipher: TWOFISH, CAMELLIA256, AES256, CAMELLIA192, AES192, CAMELLIA128, AES, BLOWFISH, IDEA, CAST5, 3DES
2546         Digest: SHA512, SHA384, SHA256, SHA224, RIPEMD160, SHA1
2547         Compression: ZLIB, BZIP2, ZIP, Uncompressed
2548         Features: MDC, Keyserver no-modify
2549
2550    bash-4.4$
2551
2552 .. _keygen-subkeys:
2553
2554 Subkeys
2555 -------
2556
2557 Adding subkeys to a primary key is fairly similar to creating the
2558 primary key with the ``create_subkey`` method. Most of the arguments are
2559 the same, but not quite all. Instead of the ``userid`` argument there is
2560 now a ``key`` argument for selecting which primary key to add the subkey
2561 to.
2562
2563 In the following example an encryption subkey will be added to the
2564 primary key. Since Danger Mouse is a security conscious secret agent,
2565 this subkey will only be valid for about six months, half the length of
2566 the primary key.
2567
2568 .. code:: python
2569
2570    import gpg
2571
2572    c = gpg.Context()
2573    c.home_dir = "~/.gnupg-dm"
2574
2575    key = c.get_key(dmkey.fpr, secret=True)
2576    dmsub = c.create_subkey(key, algorithm="rsa3072", expires_in=15768000,
2577                            encrypt=True)
2578
2579 As with the primary key, the results here can be checked with:
2580
2581 .. code:: python
2582
2583    print("""
2584     Fingerprint:  {0}
2585     Primary Key:  {1}
2586      Public Key:  {2}
2587      Secret Key:  {3}
2588     Sub Key:  {4}
2589    User IDs:  {5}
2590    """.format(dmsub.fpr, dmsub.primary, dmsub.pubkey, dmsub.seckey, dmsub.sub,
2591               dmsub.uid))
2592
2593 As well as on the command line with:
2594
2595 .. code:: shell
2596
2597    bash-4.4$ gpg --homedir ~/.gnupg-dm -K
2598    ~/.gnupg-dm/pubring.kbx
2599    ----------------------
2600    sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
2601      177B7C25DB99745EE2EE13ED026D2F19E99E63AA
2602    uid           [ultimate] Danger Mouse <dm@secret.example.net>
2603    ssb   rsa3072 2018-03-15 [E] [expires: 2018-09-13]
2604
2605    bash-4.4$
2606
2607 .. _keygen-uids:
2608
2609 User IDs
2610 --------
2611
2612 .. _keygen-uids-add:
2613
2614 Adding User IDs
2615 ~~~~~~~~~~~~~~~
2616
2617 By comparison to creating primary keys and subkeys, adding a new user ID
2618 to an existing key is much simpler. The method used to do this is
2619 ``key_add_uid`` and the only arguments it takes are for the ``key`` and
2620 the new ``uid``.
2621
2622 .. code:: python
2623
2624    import gpg
2625
2626    c = gpg.Context()
2627    c.home_dir = "~/.gnupg-dm"
2628
2629    dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
2630    key = c.get_key(dmfpr, secret=True)
2631    uid = "Danger Mouse <danger.mouse@secret.example.net>"
2632
2633    c.key_add_uid(key, uid)
2634
2635 Unsurprisingly the result of this is:
2636
2637 .. code:: shell
2638
2639    bash-4.4$ gpg --homedir ~/.gnupg-dm -K
2640    ~/.gnupg-dm/pubring.kbx
2641    ----------------------
2642    sec   rsa3072 2018-03-15 [SC] [expires: 2019-03-15]
2643      177B7C25DB99745EE2EE13ED026D2F19E99E63AA
2644    uid           [ultimate] Danger Mouse <danger.mouse@secret.example.net>
2645    uid           [ultimate] Danger Mouse <dm@secret.example.net>
2646    ssb   rsa3072 2018-03-15 [E] [expires: 2018-09-13]
2647
2648    bash-4.4$
2649
2650 .. _keygen-uids-revoke:
2651
2652 Revoking User IDs
2653 ~~~~~~~~~~~~~~~~~
2654
2655 Revoking a user ID is a fairly similar process, except that it uses the
2656 ``key_revoke_uid`` method.
2657
2658 .. code:: python
2659
2660    import gpg
2661
2662    c = gpg.Context()
2663    c.home_dir = "~/.gnupg-dm"
2664
2665    dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
2666    key = c.get_key(dmfpr, secret=True)
2667    uid = "Danger Mouse <danger.mouse@secret.example.net>"
2668
2669    c.key_revoke_uid(key, uid)
2670
2671 .. _key-sign:
2672
2673 Key certification
2674 -----------------
2675
2676 Since key certification is more frequently referred to as key signing,
2677 the method used to perform this function is ``key_sign``.
2678
2679 The ``key_sign`` method takes four arguments: ``key``, ``uids``,
2680 ``expires_in`` and ``local``. The default value of ``uids`` is ``None``
2681 and which results in all user IDs being selected. The default value of
2682 both ``expires_in`` and ``local`` is ``False``; which results in the
2683 signature never expiring and being able to be exported.
2684
2685 The ``key`` is the key being signed rather than the key doing the
2686 signing. To change the key doing the signing refer to the signing key
2687 selection above for signing messages and files.
2688
2689 If the ``uids`` value is not ``None`` then it must either be a string to
2690 match a single user ID or a list of strings to match multiple user IDs.
2691 In this case the matching of those strings must be precise and it is
2692 case sensitive.
2693
2694 To sign Danger Mouse\'s key for just the initial user ID with a
2695 signature which will last a little over a month, do this:
2696
2697 .. code:: python
2698
2699    import gpg
2700
2701    c = gpg.Context()
2702    uid = "Danger Mouse <dm@secret.example.net>"
2703
2704    dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
2705    key = c.get_key(dmfpr, secret=True)
2706    c.key_sign(key, uids=uid, expires_in=2764800)
2707
2708 .. _key-sign-verify:
2709
2710 Verifying key certifications
2711 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2712
2713 .. code:: python
2714
2715    import gpg
2716    import time
2717
2718    c = gpg.Context()
2719    dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
2720    keys = list(c.keylist(pattern=dmuid, mode=gpg.constants.keylist.mode.SIGS))
2721    key = keys[0]
2722
2723    for user in key.uids:
2724        for sig in user.signatures:
2725            print("0x{0}".format(sig.keyid), "", time.ctime(sig.timestamp), "",
2726                  sig.uid)
2727
2728 Which for Danger Mouse displays the following:
2729
2730 ::
2731
2732    0x92E3F6115435C65A  Thu Mar 15 13:17:44 2018  Danger Mouse <dm@secret.example.net>
2733    0x321E4E2373590E5D  Mon Nov 26 12:46:05 2018  Ben McGinnes <ben@adversary.org>
2734
2735 The two key signatures listed are for the self-certification of Danger
2736 Mouse\'s key made when the key was created in March, 2018; and the
2737 second is a signature made by the author and set to expire at the end of
2738 the year. Note that the second signature was made with the following
2739 code (including the preceding code to display the output of the
2740 certifications or key signatures):
2741
2742 .. code:: python
2743
2744    import gpg
2745    import math
2746    import pendulum
2747    import time
2748
2749    hd = "/home/dm/.gnupg"
2750    c = gpg.Context()
2751    d = gpg.Context(home_dir=hd)
2752    dmfpr = "177B7C25DB99745EE2EE13ED026D2F19E99E63AA"
2753    dmuid = "Danger Mouse <dm@secret.example.net>"
2754    dkeys = list(c.keylist(pattern=dmuid))
2755    dmkey = dkeys[0]
2756
2757    c.key_import(d.key_export(pattern=None))
2758
2759    tp = pendulum.period(pendulum.now(tz="local"), pendulum.datetime(2019, 1, 1))
2760    ts = tp.total_seconds()
2761    total_secs = math.ceil(ts)
2762    c.key_sign(dmkey, uids=dmuid, expires_in=total_secs)
2763
2764    d.key_import(c.key_export(pattern=dmuid))
2765    keys = list(c.keylist(pattern=dmuid, mode=gpg.constants.keylist.mode.SIGS))
2766    key = keys[0]
2767
2768    for user in key.uids:
2769        for sig in user.signatures:
2770            print("0x{0}".format(sig.keyid), "", time.ctime(sig.timestamp), "",
2771                  sig.uid)
2772
2773 Note that this final code block includes the use of a module which is
2774 *not* part of Python\'s standard library, the `pendulum
2775 module <https://pendulum.eustace.io/>`__. Unlike the standard datetime
2776 module, pendulum makes working with dates and times significantly easier
2777 in Python; just as the requests module makes working with HTTP and HTTPS
2778 easier than the builtin modules do.
2779
2780 Though neither requests nor pendulum are required modules for using the
2781 GPGME Python bindings, they are both highly recommended more generally.
2782
2783 .. _advanced-use:
2784
2785 Advanced or Experimental Use Cases
2786 ==================================
2787
2788 .. _cython:
2789
2790 C plus Python plus SWIG plus Cython
2791 -----------------------------------
2792
2793 In spite of the apparent incongruence of using Python bindings to a C
2794 interface only to generate more C from the Python; it is in fact quite
2795 possible to use the GPGME bindings with
2796 `Cython <http://docs.cython.org/en/latest/index.html>`__. Though in many
2797 cases the benefits may not be obvious since the most computationally
2798 intensive work never leaves the level of the C code with which GPGME
2799 itself is interacting with.
2800
2801 Nevertheless, there are some situations where the benefits are
2802 demonstrable. One of the better and easier examples being the one of the
2803 early examples in this HOWTO, the `key
2804 counting <#howto-keys-counting>`__ code. Running that example as an
2805 executable Python script, ``keycount.py`` (available in the
2806 ``examples/howto/`` directory), will take a noticeable amount of time to
2807 run on most systems where the public keybox or keyring contains a few
2808 thousand public keys.
2809
2810 Earlier in the evening, prior to starting this section, I ran that
2811 script on my laptop; as I tend to do periodically and timed it using
2812 ``time`` utility, with the following results:
2813
2814 .. code:: shell
2815
2816    bash-4.4$ time keycount.py
2817
2818    Number of secret keys:  23
2819    Number of public keys:  12112
2820
2821
2822    real  11m52.945s
2823    user  0m0.913s
2824    sys   0m0.752s
2825
2826    bash-4.4$
2827
2828 Sometime after that I imported another key and followed it with a little
2829 test of Cython. This test was kept fairly basic, essentially lifting the
2830 material from the `Cython Basic
2831 Tutorial <http://docs.cython.org/en/latest/src/tutorial/cython_tutorial.html>`__
2832 to demonstrate compiling Python code to C. The first step was to take
2833 the example key counting code quoted previously, essentially from the
2834 importing of the ``gpg`` module to the end of the script:
2835
2836 .. code:: python
2837
2838    import gpg
2839
2840    c = gpg.Context()
2841    seckeys = c.keylist(pattern=None, secret=True)
2842    pubkeys = c.keylist(pattern=None, secret=False)
2843
2844    seclist = list(seckeys)
2845    secnum = len(seclist)
2846
2847    publist = list(pubkeys)
2848    pubnum = len(publist)
2849
2850    print("""
2851        Number of secret keys:  {0}
2852        Number of public keys:  {1}
2853
2854    """.format(secnum, pubnum))
2855
2856 Save that into a file called ``keycount.pyx`` and then create a
2857 ``setup.py`` file which contains this:
2858
2859 .. code:: python
2860
2861    from distutils.core import setup
2862    from Cython.Build import cythonize
2863
2864    setup(
2865        ext_modules = cythonize("keycount.pyx")
2866    )
2867
2868 Compile it:
2869
2870 .. code:: shell
2871
2872    bash-4.4$ python setup.py build_ext --inplace
2873    bash-4.4$
2874
2875 Then run it in a similar manner to ``keycount.py``:
2876
2877 .. code:: shell
2878
2879    bash-4.4$ time python3.7 -c "import keycount"
2880
2881    Number of secret keys:  23
2882    Number of public keys:  12113
2883
2884
2885    real  6m47.905s
2886    user  0m0.785s
2887    sys   0m0.331s
2888
2889    bash-4.4$
2890
2891 Cython turned ``keycount.pyx`` into an 81KB ``keycount.o`` file in the
2892 ``build/`` directory, a 24KB ``keycount.cpython-37m-darwin.so`` file to
2893 be imported into Python 3.7 and a 113KB ``keycount.c`` generated C
2894 source code file of nearly three thousand lines. Quite a bit bigger than
2895 the 314 bytes of the ``keycount.pyx`` file or the full 1,452 bytes of
2896 the full executable ``keycount.py`` example script.
2897
2898 On the other hand it ran in nearly half the time; taking 6 minutes and
2899 47.905 seconds to run. As opposed to the 11 minutes and 52.945 seconds
2900 which the CPython script alone took.
2901
2902 The ``keycount.pyx`` and ``setup.py`` files used to generate this
2903 example have been added to the ``examples/howto/advanced/cython/``
2904 directory The example versions include some additional options to
2905 annotate the existing code and to detect Cython\'s use. The latter comes
2906 from the `Magic
2907 Attributes <http://docs.cython.org/en/latest/src/tutorial/pure.html#magic-attributes-within-the-pxd>`__
2908 section of the Cython documentation.
2909
2910 .. _cheats-and-hacks:
2911
2912 Miscellaneous extras and work-arounds
2913 =====================================
2914
2915 Most of the things in the following sections are here simply because
2916 there was no better place to put them, even though some are only
2917 peripherally related to the GPGME Python bindings. Some are also
2918 workarounds for functions not integrated with GPGME as yet. This is
2919 especially true of the first of these, dealing with `group
2920 lines <#group-lines>`__.
2921
2922 Group lines
2923 -----------
2924
2925 There is not yet an easy way to access groups configured in the gpg.conf
2926 file from within GPGME. As a consequence these central groupings of keys
2927 cannot be shared amongst multiple programs, such as MUAs readily.
2928
2929 The following code, however, provides a work-around for obtaining this
2930 information in Python.
2931
2932 .. code:: python
2933
2934    import subprocess
2935    import sys
2936
2937    if sys.platform == "win32":
2938        gpgconfcmd = "gpgconf.exe --list-options gpg"
2939    else:
2940        gpgconfcmd = "gpgconf --list-options gpg"
2941
2942    try:
2943        lines = subprocess.getoutput(gpgconfcmd).splitlines()
2944    except:
2945        process = subprocess.Popen(gpgconfcmd.split(), stdout=subprocess.PIPE)
2946        procom = process.communicate()
2947        if sys.version_info[0] == 2:
2948            lines = procom[0].splitlines()
2949        else:
2950            lines = procom[0].decode().splitlines()
2951
2952    for i in range(len(lines)):
2953        if lines[i].startswith("group") is True:
2954            line = lines[i]
2955        else:
2956            pass
2957
2958    groups = line.split(":")[-1].replace('"', '').split(',')
2959
2960    group_lines = []
2961    group_lists = []
2962
2963    for i in range(len(groups)):
2964        group_lines.append(groups[i].split("="))
2965        group_lists.append(groups[i].split("="))
2966
2967    for i in range(len(group_lists)):
2968        group_lists[i][1] = group_lists[i][1].split()
2969
2970 The result of that code is that ``group_lines`` is a list of lists where
2971 ``group_lines[i][0]`` is the name of the group and ``group_lines[i][1]``
2972 is the key IDs of the group as a string.
2973
2974 The ``group_lists`` result is very similar in that it is a list of
2975 lists. The first part, ``group_lists[i][0]`` matches
2976 ``group_lines[i][0]`` as the name of the group, but
2977 ``group_lists[i][1]`` is the key IDs of the group as a list.
2978
2979 A demonstration of using the ``groups.py`` module is also available in
2980 the form of the executable ``mutt-groups.py`` script. This second script
2981 reads all the group entries in a user\'s ``gpg.conf`` file and converts
2982 them into crypt-hooks suitable for use with the Mutt and Neomutt mail
2983 clients.
2984
2985 .. _hkp4py:
2986
2987 Keyserver access for Python
2988 ---------------------------
2989
2990 The `hkp4py <https://github.com/Selfnet/hkp4py>`__ module by Marcel Fest
2991 was originally a port of the old
2992 `python-hkp <https://github.com/dgladkov/python-hkp>`__ module from
2993 Python 2 to Python 3 and updated to use the
2994 `requests <http://docs.python-requests.org/en/latest/index.html>`__
2995 module instead. It has since been modified to provide support for Python
2996 2.7 as well and is available via PyPI.
2997
2998 Since it rewrites the ``hkp`` protocol prefix as ``http`` and ``hkps``
2999 as ``https``, the module is able to be used even with servers which do
3000 not support the full scope of keyserver functions. [5]_ It also works
3001 quite readily when incorporated into a `Cython <#cython>`__ generated
3002 and compiled version of any code.
3003
3004 .. _hkp4py-strings:
3005
3006 Key import format
3007 ~~~~~~~~~~~~~~~~~
3008
3009 The hkp4py module returns key data via requests as string literals
3010 (``r.text``) instead of byte literals (``r.content``). This means that
3011 the retrurned key data must be encoded to UTF-8 when importing that key
3012 material using a ``gpg.Context().key_import()`` method.
3013
3014 For this reason an alternative method has been added to the ``search``
3015 function of ``hkp4py.KeyServer()`` which returns the key in the correct
3016 format as expected by ``key_import``. When importing using this module,
3017 it is now possible to import with this:
3018
3019 .. code:: python
3020
3021    for key in keys:
3022        if key.revoked is False:
3023            gpg.Context().key_import(key.key_blob)
3024        else:
3025            pass
3026
3027 Without that recent addition it would have been necessary to encode the
3028 contents of each ``hkp4py.KeyServer().search()[i].key`` in
3029 ``hkp4py.KeyServer().search()`` before trying to import it.
3030
3031 An example of this is included in the `Importing
3032 Keys <#howto-import-key>`__ section of this HOWTO and the corresponding
3033 executable version of that example is available in the
3034 ``lang/python/examples/howto`` directory as normal; the executable
3035 version is the ``import-keys-hkp.py`` file.
3036
3037 .. _gpgme-version-check:
3038
3039 GPGME version checking
3040 ----------------------
3041
3042 For various reasons it may be necessary to check which version of GPGME
3043 the bindings have been built against; including whether a minimum
3044 required version of GPGME is in use.
3045
3046 For the most part the ``gpg.version.versionstr`` and
3047 ``gpg.version.versionlist`` methods have been quite sufficient. The
3048 former returns the same string as ``gpgme-config --version``, while the
3049 latter returns the major, minor and patch values in a list.
3050
3051 To check if the installed bindings have actually been built against the
3052 current installed libgpgme version, this check can be performed:
3053
3054 .. code:: python
3055
3056    import gpg
3057    import subprocess
3058    import sys
3059
3060    gpgme_version_call = subprocess.Popen(["gpgme-config", "--version"],
3061                                          stdout=subprocess.PIPE,
3062                                          stderr=subprocess.PIPE)
3063    gpgme_version_str = gpgme_version_call.communicate()
3064
3065    if sys.version_info[0] == 2:
3066        gpgme_version = gpgme_version_str[0].strip()
3067    elif sys.version_info[0] >= 3:
3068        gpgme_version = gpgme_version_str[0].decode().strip()
3069    else:
3070        gpgme_version = None
3071
3072    if gpgme_version is not None:
3073        if gpgme_version == gpg.version.versionstr:
3074            print("The GPGME Python bindings match libgpgme.")
3075        else:
3076            print("The GPGME Python bindings do NOT match libgpgme.")
3077    else:
3078        print("Upgrade Python and reinstall the GPGME Python bindings.")
3079
3080 For many developers, however, the preferred checking means checking for
3081 a minimum version or point release. This is now readily available via
3082 the ``gpg.version.versionintlist`` method (added in version
3083 ``1.12.1-beta79``). It is also now possible to easily check whether the
3084 installed GPGME Python bindings were built from a development or beta
3085 branch of the GPGME source code.
3086
3087 The following code demonstrates how both of those methods may be used:
3088
3089 .. code:: python
3090
3091    import gpg
3092
3093    try:
3094        if gpg.version.is_beta is True:
3095            print("The installed GPGME Python bindings were built from beta code.")
3096        else:
3097            print("The installed GPGME Python bindings are a released version.")
3098    except Exception as e:
3099        print(e)
3100
3101    try:
3102        if gpg.version.versionintlist[0] == 1:
3103            if gpg.version.versionintlist[1] == 12:
3104                if gpg.version.versionintlist[2] == 1:
3105                    print("This is the minimum version for using versionintlist.")
3106                elif gpg.version.versionintlist[2] > 1:
3107                    print("The versionintlist method is available.")
3108                else:
3109                    pass
3110            elif gpg.version.versionintlist[1] > 12:
3111                print("The versionintlist method is available.")
3112            else:
3113                pass
3114        elif gpg.version.versionintlist[0] > 1:
3115            print("The versionintlist method is available.")
3116        else:
3117            pass
3118    except Exception as e:
3119        print(e)
3120
3121 The points where ``pass`` is used in the above example will most likely
3122 also produce an ``Exception`` error since those results should only
3123 occur in versions which do not have the ``gpgme.version.is_beta`` and
3124 ``gpgme.version.versionintlist`` methods available.
3125
3126 .. _copyright-and-license:
3127
3128 Copyright and Licensing
3129 =======================
3130
3131 Copyright
3132 ---------
3133
3134 Copyright © The GnuPG Project, 2018.
3135
3136 Copyright (C) The GnuPG Project, 2018.
3137
3138 .. _draft-editions:
3139
3140 Draft Editions of this HOWTO
3141 ----------------------------
3142
3143 Draft editions of this HOWTO may be periodically available directly from
3144 the author at any of the following URLs:
3145
3146 -  `GPGME Python Bindings HOWTO draft (XHTML single file, AWS S3
3147    SSL) <https://files.au.adversary.org/crypto/gpgme-python-howto.html>`__
3148 -  `GPGME Python Bindings HOWTO draft (XHTML single file, AWS S3 no
3149    SSL) <http://files.au.adversary.org/crypto/gpgme-python-howto.html>`__
3150 -  `GPGME Python Bindings HOWTO draft (XHTML multiple files, AWS S3
3151    SSL) <https://files.au.adversary.org/crypto/gpgme-python-howto-split/index.html>`__
3152 -  `GPGME Python Bindings HOWTO draft (XHTML multiple files, AWS S3 no
3153    SSL) <http://files.au.adversary.org/crypto/gpgme-python-howto/index.html>`__
3154
3155 All of these draft versions except for one have been generated from this
3156 document via GNU Emacs `Org mode <https://orgmode.org/>`__ and `GNU
3157 Texinfo <https://www.gnu.org/software/texinfo/>`__. Though it is likely
3158 that the specific
3159 `file <https://files.au.adversary.org/crypto/gpgme-python-howto>`__
3160 `version <http://files.au.adversary.org/crypto/gpgme-python-howto.org>`__
3161 used will be on the same server with the generated output formats.
3162
3163 The GNU Texinfo and reStructured Text versions ship with the software,
3164 while the GNU Emacs Info verseion is generated from the Texinfo version
3165 using GNU Texinfo or GNU Makeinfo. The Texinfo format is generated from
3166 the original Org mode source file in Org mode itself either within GNU
3167 Emacs or via the command line by invoking Emacs in batch mode:
3168
3169 .. code:: shell
3170
3171    emacs gpgme-python-howto.org --batch -f org-texinfo-export-to-texinfo --kill
3172    emacs gpgme-python-howto --batch -f org-texinfo-export-to-texinfo --kill
3173
3174 The reStructuredText format is also generated from the Org-mode source
3175 file, except it is generated using `Pandoc <https://pandoc.org>`__ with
3176 either of the following commands:
3177
3178 .. code:: shell
3179
3180    pandoc -f org -t rst+smart -o gpgme-python-howto.rst gpgme-python-howto.org
3181    pandoc -f org -t rst+smart -o gpgme-python-howto.rst gpgme-python-howto
3182
3183 In addition to these there is a significantly less frequently updated
3184 version as a HTML `WebHelp
3185 site <https://files.au.adversary.org/crypto/gpgme-python/dita/webhelp/index.html>`__
3186 (AWS S3 SSL); generated from DITA XML source files, which can be found
3187 in `an alternative
3188 branch <https://dev.gnupg.org/source/gpgme/browse/ben%252Fhowto-dita/>`__
3189 of the GPGME git repository.
3190
3191 Various generated output formats may occasionally be found in
3192 subdirectories of the
3193 `gpgme-python <https://s3.amazonaws.com/files.au.adversary.org/crypto/gpgme-python>`__
3194 directory. In particular within the
3195 `DITA <https://s3.amazonaws.com/files.au.adversary.org/crypto/gpgme-python/dita>`__,
3196 `reStructuredText <https://s3.amazonaws.com/files.au.adversary.org/crypto/gpgme-python/rst>`__
3197 and
3198 `Texinfo <https://s3.amazonaws.com/files.au.adversary.org/crypto/gpgme-python/texinfo>`__
3199 subdirectories. The ``rst`` directory contains output files generated
3200 with Sphix and may include a considerable number of its possible output
3201 formats.
3202
3203 These draft editions are not official documents and the version of
3204 documentation in the master branch or which ships with released versions
3205 is the only official documentation. Nevertheless, these draft editions
3206 may occasionally be of use by providing more accessible web versions
3207 which are updated between releases. They are provided on the
3208 understanding that they may contain errors or may contain content
3209 subject to change prior to an official release.
3210
3211 .. _license:
3212
3213 License GPL compatible
3214 ----------------------
3215
3216 This file is free software; as a special exception the author gives
3217 unlimited permission to copy and/or distribute it, with or without
3218 modifications, as long as this notice is preserved.
3219
3220 This file is distributed in the hope that it will be useful, but WITHOUT
3221 ANY WARRANTY, to the extent permitted by law; without even the implied
3222 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
3223
3224 Footnotes
3225 =========
3226
3227 .. [1]
3228    ``short-history`` and/or ``short-history.html``.
3229
3230 .. [2]
3231    With no issues reported specific to Python 3.7, the release of Python
3232    3.7.1 at around the same time as GPGME 1.12.0 and the testing with
3233    Python 3.7.1rc1, there is no reason to delay moving 3.7 ahead of 3.6
3234    now. Production environments with more conservative requirements will
3235    always enforce their own policies anyway and installation to each
3236    supported minor release is quite possible too.
3237
3238 .. [3]
3239    Yes, even if you use virtualenv with everything you do in Python. If
3240    you want to install this module as just your user account then you
3241    will need to manually configure, compile and install the *entire*
3242    GnuPG stack as that user as well. This includes libraries which are
3243    not often installed that way. It can be done and there are
3244    circumstances under which it is worthwhile, but generally only on
3245    POSIX systems which utilise single user mode (some even require it).
3246
3247 .. [4]
3248    You probably don\'t really want to do this. Searching the keyservers
3249    for \"gnupg.org\" produces over 400 results, the majority of which
3250    aren\'t actually at the gnupg.org domain, but just included a comment
3251    regarding the project in their key somewhere.
3252
3253 .. [5]
3254    Such as with ProtonMail servers. This also means that restricted
3255    servers which only advertise either HTTP or HTTPS end points and not
3256    HKP or HKPS end points must still be identified as as HKP or HKPS
3257    within the Python Code. The ``hkp4py`` module will rewrite these
3258    appropriately when the connection is made to the server.