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