doc: python bindings HOWTO
[gpgme.git] / lang / python / docs / GPGMEpythonHOWTOen.org
1 #+TITLE: GNU Privacy Guard (GnuPG)  Made Easy Python Bindings HOWTO (English)
2 #+LATEX_COMPILER: xelatex
3 #+LATEX_CLASS: article
4 #+LATEX_CLASS_OPTIONS: [12pt]
5 #+LATEX_HEADER: \usepackage{xltxtra}
6 #+LATEX_HEADER: \usepackage[margin=1in]{geometry}
7 #+LATEX_HEADER: \setmainfont[Ligatures={Common}]{Times New Roman}
8 #+LATEX_HEADER: \author{Ben McGinnes <ben@gnupg.org>}
9
10
11 * Introduction
12   :PROPERTIES:
13   :CUSTOM_ID: intro
14   :END:
15
16   Version: 0.0.1-alpha [2018-03-07 Wed]
17   Author: Ben McGinnes <ben@gnupg.org>
18   Author GPG Key: DB4724E6FA4286C92B4E55C4321E4E2373590E5D
19
20   This document provides basic instruction in how to use the GPGME
21   Python bindings to programmatically leverage the GPGME library.
22
23
24 * GPGME Concepts
25   :PROPERTIES:
26   :CUSTOM_ID: gpgme-concepts
27   :END:
28
29 ** A C API
30    :PROPERTIES:
31    :CUSTOM_ID: gpgme-c-api
32    :END:
33
34    Unlike many modern APIs with which programmers will be more
35    familiar with these days, the GPGME API is a C API.  The API is
36    intended for use by C coders who would be able to access its
37    features by including the =gpgme.h= header file eith their own C
38    source code and then access its functions just as they would any
39    other C headers.
40
41    This is a very effective method of gaining complete access to the
42    API and in the most efficient manner possible.  It does, however,
43    have the drawback that it cannot be directly used by other
44    languages without some means of providing an interface to those
45    languages.  This is where the need for bindings in various
46    languages stems.
47
48 ** Python bindings
49    :PROPERTIES:
50    :CUSTOM_ID: gpgme-python-bindings
51    :END:
52
53    The Python bindings for GPGME provide a higher level means of
54    accessing the complete feature set of GPGME itself.  It also
55    provides a more pythonic means of calling these API functions.
56
57    The bindings are generated dynamically with SWIG and the copy of
58    =gpgme.h= generated when GPGME is compiled.
59
60    This means that a version of the Python bindings is fundamentally
61    tied to the exact same version of GPGME used to gemerate that copy
62    of =gpgme.h=.
63
64 ** Difference between the Python bindings and other GnuPG Python packages
65    :PROPERTIES:
66    :CUSTOM_ID: gpgme-python-bindings-diffs
67    :END:
68
69    There have been numerous attempts to add GnuPG support to Python
70    over the years.  Some of the most well known are listed here, along
71    with what differentiates them.
72
73 *** The python-gnupg package maintained by Vinay Sajip
74     :PROPERTIES:
75     :CUSTOM_ID: diffs-python-gnupg
76     :END:
77
78     This is arguably the most popular means of integrating GPG with
79     Python.  The package utilises the =subprocess= module to implement
80     wrappers for the =gpg= and =gpg2= executables normally invoked on
81     the command line (=gpg.exe= and =gpg2.exe= on Windows).
82
83     The popularity of this package stemmed from its ease of use and
84     capability in providing the most commonly required features.
85
86     Unfortunately it has been beset by a number of security issues,
87     most of which stemmed from using unsafe methods of accessing the
88     command line via the =subprocess= calls.
89
90     The python-gnupg package is available under the MIT license.
91
92 *** The gnupg package created and maintained by Isis Lovecruft
93     :PROPERTIES:
94     :CUSTOM_ID: diffs-isis-gnupg
95     :END:
96
97     In 2015 Isis Lovecruft from the Tor Project forked and then
98     re-implemented the python-gnupg package as just gnupg.  This new
99     package also relied on subprocess to call the =gpg= or =gpg2=
100     binaries, but did so somewhat more securely.
101
102     However the naming and version numbering selected for this package
103     resulted in conflicts with the original python-gnupg and since its
104     functions were called in a different manner, the release of this
105     package also resulted in a great deal of consternation when people
106     installed what they thought was an upgrade that subsequently broke
107     the code relying on it.
108
109     The gnupg package is available under the GNU General Public
110     License version 3.0 (or later).
111
112 *** The PyME package maintained by Martin Albrecht
113     :PROPERTIES:
114     :CUSTOM_ID: diffs-pyme
115     :END:
116
117     This package is the origin of these bindings, though they are
118     somewhat different now.  For details of when and how the PyME
119     package was folded back into GPGME itself see the [[Short_History.org][Short History]]
120     document in this Python bindings =docs= directory.
121
122     The PyME package was first released in 2002 and was also the first
123     attempt to implement a low level binding to GPGME.  In doing so it
124     provided access to considerably more functionality than either the
125     =python-gnupg= or =gnupg= packages.
126
127     The PyME package is only available for Python 2.6 and 2.7.
128
129     Porting the PyME package to Python 3.4 in 2015 is what resulted in
130     it being folded into the GPGME project and the current bindings
131     are the end result of that effort.
132
133     The PyME package is available under the same dual licensing as
134     GPGME itself: the GNU General Public License version 2.0 (or any
135     later version) and the GNU Lesser Public License version 2.1 (or
136     any later version).
137
138
139 * GPGME Python bindings installation
140   :PROPERTIES:
141   :CUSTOM_ID: gpgme-python-install
142   :END:
143
144 ** No PyPI
145    :PROPERTIES:
146    :CUSTOM_ID: do-not-use-pypi
147    :END:
148
149    Most third-party Python packages and modules are available and
150    distributed through the Python Package Installer, known as PyPI.
151
152    Due to the nature of what these bindings are and how they work, it
153    is infeasible to install the GPGME Python bindings in the same way.
154
155 ** Requirements
156    :PROPERTIES:
157    :CUSTOM_ID: gpgme-python-requirements
158    :END:
159
160    The GPGME Python bindings only have three requirements:
161
162    1. A suitable version of Python 2 or Python 3.  With Python 2 that
163       means Python 2.7 and with Python 3 that means Python 3.4 or
164       higher.
165    2. SWIG.
166    3. GPGME itself.  Which also means that all of GPGME's dependencies
167       must be installed too.
168
169 ** Installation
170    :PROPERTIES:
171    :CUSTOM_ID: installation
172    :END:
173
174    Installing the Python bindings is effectively achieved by compiling
175    and installing GPGME itself.
176
177    Once SWIG is installed with Python and all the dependencies for
178    GPGME are installed you only need to confirm that the version(s) of
179    Python you want the bindings installed for are in your =$PATH=.
180
181    By default GPGME will attempt to install the bindings for the most
182    recent or highest version number of Python 2 and Python 3 it
183    detects in =$PATH=.  It specifically checks for the =python= and
184    =python3= executabled first and then checks for specific version
185    numbers.
186
187    For Python 2 it checks for these executables in this order:
188    =python=, =python2= and =python2.7=.
189
190    For Python 3 it checks for these executables in this order:
191    =python3=, =python3.6=, =python3.5= and =python3.4=.
192
193 *** Installing GPGME
194     :PROPERTIES:
195     :CUSTOM_ID: install-gpgme
196     :END:
197
198     See the [[../../../README][GPGME README file]] for details of how to install GPGME from
199     source.
200
201
202 * Fundamentals
203   :PROPERTIES:
204   :CUSTOM_ID: howto-fund-a-mental
205   :END:
206
207   Before we can get to the fun stuff, there are a few matters
208   regarding GPGME's design which hold true whether you're dealing with
209   the C code directly or these Python bindings.
210
211 ** No REST
212    :PROPERTIES:
213    :CUSTOM_ID: no-rest-for-the-wicked
214    :END:
215
216    The first part of which is or will be fairly blatantly obvious upon
217    viewing the first example, but it's worth reiterating anyway.  That
218    being that this API is /*not*/ a REST API.  Nor indeed could it
219    ever be one.
220
221    Most, if not all, Python programmers (and not just Python
222    programmers) know how easy it is to work with a RESTful API.  In
223    fact they've become so popular that many other APIs attempt to
224    emulate REST-like behaviour as much as they are able.  Right down
225    to the use of JSON formatted output to facilitate the use of their
226    API without having to retrain developers.
227
228    This API does not do that.  It would not be able to do that and
229    also provide access to the entire C API on which it's built.  It
230    does, however, provide a very pythonic interface on top of the
231    direct bindings and it's this pythonic layer with which this HOWTO
232    deals with.
233
234 ** Context
235    :PROPERTIES:
236    :CUSTOM_ID: howto-get-context
237    :END:
238
239    One of the reasons which prevents this API from being RESTful is
240    that most operations require more than one instruction to the API
241    to perform the task.  Sure, there are certain functions which can
242    be performed simultaneously, particularly if the result known or
243    strongly anticipated (e.g selecting and encrypting to a key known
244    to be in the public keybox).
245
246    There are many more, however, which cannot be manipulated so
247    readily: they must be performed in a specific sequence and the
248    result of one operation has a direct bearing on the outcome of
249    subsequent operations.  Not merely by generating an error either.
250
251    When dealing with this type of persistant state on the web, full of
252    both the RESTful and REST-like, it's most commonly referred to as a
253    session.  In GPGME, however, it is called a context and every
254    operation type has one.
255
256
257 * Basic Functions
258   :PROPERTIES:
259   :CUSTOM_ID: howto-the-basics
260   :END:
261
262   The most frequently called features of any cryptographic library
263   will be the most fundamental tasks for enxryption software.  In this
264   section we will look at how to programmatically encrypt data,
265   decrypt it, sign it and verify signatures.
266
267 ** Encryption
268    :PROPERTIES:
269    :CUSTOM_ID: howto-basic-encryption
270    :END:
271
272    Encrypting is very straight forward.  In the first example below
273    the message, =text=, is encrypted to a single recipient's key.  In
274    the second example the message will be encrypted to multiple
275    recipients.
276
277 *** Encrypting to one key
278     :PROPERTIES:
279     :CUSTOM_ID: howto-basic-encryption-single
280     :END:
281
282    The text is then encapsulated in a GPGME Data object as =plain= and
283    the =cipher= object is created with another Data object.  Then we
284    create the Context as =c= and set it to use the ASCII armoured
285    OpenPGP format.  In later examples there will be alternative
286    methods of setting the OpenPGP output to be ASCII armoured.
287
288    Next we prepare a keylist object in our Context and follow it with
289    specifying the recipients as =r=.  Note that the configuration in
290    one's =gpg.conf= file is honoured, so if you have the options set
291    to encrypt to one key or to a default key, that will be included
292    with this operation.
293
294    This is followed by a quick check to be sure that the recipient is
295    actually selected and that the key is available.  Assuming it is,
296    the encryption can proceed, but if not a message will print stating
297    the key was not found.
298
299    The encryption operation is invoked within the Context with the
300    =c.op_encrypt= function, loading the recipien (=r=), the message
301    (=plain=) and the =cipher=.  The =cipher.seek= uses =os.SEEK_SET=
302    to set the data to the correct byte format for GPGME to use it.
303
304    At this point we no longer need the plaintext material, so we
305    delete both the =text= and the =plain= objects.  Then we write the
306    encrypted data out to a file, =secret_plans.txt.asc=.
307
308    #+begin_src python
309      import gpg
310      import os
311
312      rkey = "0x12345678DEADBEEF"
313      text = """
314      Some plain text to test with.  Obtained from any input source Python can read.
315
316      It makes no difference whether it is string or bytes, but the bindings always
317      produce byte output data.  Which is useful to know when writing out either the
318      encrypted or decrypted results.
319
320      """
321
322      plain = gpg.core.Data(text)
323      cipher = gpg.core.Data()
324      c = gpg.core.Context()
325      c.set_armor(1)
326
327      c.op_keylist_start(rkey, 0)
328      r = c.op_keylist_next()
329
330      if r == None:
331          print("""The key for user "{0}" was not found""".format(rkey))
332      else:
333          try:
334              c.op_encrypt([r], 1, plain, cipher)
335              cipher.seek(0, os.SEEK_SET)
336              del(text)
337              del(plain)
338              afile = open("secret_plans.txt.asc", "wb")
339              afile.write(cipher.read())
340              afile.close()
341          except gpg.errors.GPGMEError as ex:
342              print(ex.getstring())
343    #+end_src
344
345 *** Encrypting to multiple keys
346     :PROPERTIES:
347     :CUSTOM_ID: howto-basic-encryption-multiple
348     :END:
349
350
351 ** Decryption
352    :PROPERTIES:
353    :CUSTOM_ID: howto-basic-encryption
354    :END:
355
356    Decrypting something encrypted to a key in one's secret keyring
357    (will display some extra data you normally wouldn't show, but which
358    may be of use):
359
360    #+begin_src python
361      import os.path
362      import gpg
363
364      if os.path.exists("/path/to/secret_plans.txt.asc") is True:
365          ciphertext = "/path/to/secret_plans.txt.asc"
366      elif os.path.exists("/path/to/secret_plans.txt.gpg") is True:
367          ciphertext = "/path/to/secret_plans.txt.gpg"
368      else:
369          ciphertext = None
370
371      if ciphertext is not None:
372          afile = open(ciphertext, "rb")
373          plaintext = gpg.Context().decrypt(afile)
374          afile.close()
375          newfile = open("/path/to/secret_plans.txt", "wb")
376          newfile.write(plaintext[0])
377          newfile.close()
378          print(plaintext[0])
379          plaintext[1]
380          plaintext[2]
381          del(plaintext)
382      else:
383          pass
384    #+end_src
385
386
387 ** Signing text
388    :PROPERTIES:
389    :CUSTOM_ID: howto-basic-signing
390    :END:
391
392    Need to determine whether or not to include clearsigning and
393    detached signing here or give them separate sections.
394
395    #+begin_src python
396      import gpg
397
398      text = """Declaration of ... something.
399
400      """
401
402      c = gpg.Context()
403      c.armor = True
404      signed = c.sign(text, mode=mode.NORMAL)
405
406      afile = open("/path/to/statement.txt.asc", "w")
407      for i in range(len(signed[0].splitlines())):
408          afile.write("{0}\n".format(signed[0].splitlines()[i].decode('utf-8')))
409      afile.close()
410    #+end_src
411
412    Clearsigning:
413
414    #+begin_src python
415      import gpg
416
417      text = """Declaration of ... something.
418
419      """
420
421      c = gpg.Context()
422      c.armor = True
423      signed = c.sign(text, mode=mode.CLEAR)
424
425      afile = open("/path/to/statement.txt.asc", "w")
426      for i in range(len(signed[0].splitlines())):
427          afile.write("{0}\n".format(signed[0].splitlines()[i].decode('utf-8')))
428      afile.close()
429    #+end_src
430
431    Detached ASCII Armoured signing:
432
433    #+begin_src python
434      import gpg
435
436      text = """Declaration of ... something.
437
438      """
439
440      c = gpg.Context()
441      c.armor = True
442      signed = c.sign(text, mode=mode.DETACH)
443
444      afile = open("/path/to/statement.txt.asc", "w")
445      for i in range(len(signed[0].splitlines())):
446          afile.write("{0}\n".format(signed[0].splitlines()[i].decode('utf-8')))
447      afile.close()
448    #+end_src
449
450    Detached binary signing of a file.
451
452    #+begin_src python
453      import gpg
454
455      tfile = open("/path/to/statement.txt", "r")
456      text = tfile.read()
457      tfile.close()
458
459      c = gpg.Context()
460      c.armor = True
461      signed = c.sign(text, mode=mode.DETACH)
462
463      afile = open("/path/to/statement.txt.sig", "wb")
464      afile.write(signed[0])
465      afile.close()
466    #+end_src
467
468
469 ** Signature verification
470    :PROPERTIES:
471    :CUSTOM_ID: howto-basic-verification
472    :END:
473
474    Verify a signed file, both detached and not:
475
476    #+begin_src python
477      import gpg
478      import sys
479      import time
480
481      c = gpg.Context()
482
483      data, result = c.verify(open(filename),
484                              open(detached_sig_filename)
485                              if detached_sig_filename else None)
486
487      for index, sign in enumerate(result.signatures):
488          print("signature", index, ":")
489          print("  summary:     %#0x" % (sign.summary))
490          print("  status:      %#0x" % (sign.status))
491          print("  timestamp:  ", sign.timestamp)
492          print("  timestamp:  ", time.ctime(sign.timestamp))
493          print("  fingerprint:", sign.fpr)
494          print("  uid:        ", c.get_key(sign.fpr).uids[0].uid)
495
496      if data:
497          sys.stdout.buffer.write(data)
498    #+end_src
499
500
501 * Working with keys
502   :PROPERTIES:
503   :CUSTOM_ID: howto-keys
504   :END:
505
506 ** Counting keys
507    :PROPERTIES:
508    :CUSTOM_ID: howto-basic-verification
509    :END:
510
511    Counting the number of keys in your public keybox (=pubring.kbx=),
512    the format shich has superceded the old keyring format
513    (=pubring.gpg= and =secring.gpg=) is a very simple task.
514
515    #+begin_src python
516      import gpg
517
518      c = gpg.Context()
519      seckeys = c.keylist(pattern=None, secret=True)
520      pubkeys = c.keylist(pattern=None, secret=False)
521
522      seclist = list(seckeys)
523      secnum = len(seclist)
524
525      publist = list(pubkeys)
526      pubnum = len(publist)
527
528      print("""
529      Number of secret keys:  {0}
530      Number of public keys:  {1}
531      """.format(secnum, pubnum)
532    #+end_src
533
534 * Copyright and Licensing
535   :PROPERTIES:
536   :CUSTOM_ID: copyright-and-license
537   :END:
538
539 ** Copyright (C) The GnuPG Project, 2018
540    :PROPERTIES:
541    :CUSTOM_ID: copyright
542    :END:
543
544    Copyright © The GnuPG Project, 2018.
545
546 ** License GPL compatible
547    :PROPERTIES:
548    :CUSTOM_ID: license
549    :END:
550
551    This file is free software; as a special exception the author gives
552    unlimited permission to copy and/or distribute it, with or without
553    modifications, as long as this notice is preserved.
554
555    This file is distributed in the hope that it will be useful, but
556    WITHOUT ANY WARRANTY, to the extent permitted by law; without even
557    the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
558    PURPOSE.