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