From f0063afa71bc7e71f19d174acc2fde26f0c11850 Mon Sep 17 00:00:00 2001
From: Ben McGinnes Unlike all other documentation in the GnuPG Project, including the initial version of
+ this HOWTO, this version was not written in Emacs Org-Mode. Nor was it written in
+ LaTeX, Texinfo or even directly in HTML. Instead it was written using the Darwin Information
+ Typing Architecture (DITA) XML. This was done for two main reasons:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
The XML format definitely supports displaying all the more complex Python code correctly, + as well as being designed to produce standards compliant print and HTML output. Whereas + currently the existing tools utilised by the GnuPG Project can't display the example code in + a way which would actually pass the project's own git commit ruleset.
++ + + diff --git a/lang/python/docs/dita/howto/part01/examples.dita b/lang/python/docs/dita/howto/part01/examples.dita new file mode 100644 index 00000000..afa66197 --- /dev/null +++ b/lang/python/docs/dita/howto/part01/examples.dita @@ -0,0 +1,11 @@ + + +
All of the examples found in this document can be found as Python 3 scripts in the
+
This document provides basic instruction in how to use the GPGME Python bindings to + programmatically leverage the GPGME library.
+ +Though the GPGME Python bindings themselves provide support for both Python 2 and 3, + the focus is unequivocally on Python 3 and specifically from Python 3.4 and above. As a + consequence all the examples and instructions in this guide use Python 3 code.
+Much of it will work with Python 2, but much of it also deals with Python 3 byte literals, + particularly when reading and writing data. Developers concentrating on Python 2.7, and + possibly even 2.6, will need to make the appropriate modifications to support the older + string and unicode types as opposed to bytes.
+There are multiple reasons for concentrating on Python 3; some of which relate to the + immediate integration of these bindings, some of which relate to longer term plans for both + GPGME and the python bindings and some of which relate to the impending EOL period for + Python 2.7. Essentially, though, there is little value in tying the bindings to a version of + the language which is a dead end and the advantages offered by Python 3 over Python 2 make + handling the data types with which GPGME deals considerably easier.
+ +Unlike many modern APIs with which programmers will be more familiar with these days, + the GPGME API is a C API. The API is intended for use by C coders who would be able to + access its features by including the =gpgme.h= header file with their own C source code and + then access its functions just as they would any other C headers.
+This is a very effective method of gaining complete access to the API and in the most + efficient manner possible. It does, however, have the drawback that it cannot be directly + used by other languages without some means of providing an interface to those languages. + This is where the need for bindings in various languages stems.
+ +One of the reasons which prevents this API from being RESTful is that most operations + require more than one instruction to the API to perform the task. Sure, there are certain + functions which can be performed simultaneously, particularly if the result known or + strongly anticipated (e.g. selecting and encrypting to a key known to be in the public + keybox).
+There are many more, however, which cannot be manipulated so readily: they must be + performed in a specific sequence and the result of one operation has a direct bearing on the + outcome of subsequent operations. Not merely by generating an error either.
+When dealing with this type of persistent state on the web, full of both the RESTful and + REST-like, it's most commonly referred to as a session. In GPGME, however, it is called a + context and every operation type has one.
+ + +In 2015 Isis Lovecruft from the Tor Project forked and then re-implemented the
+ python-gnupg package as just gnupg. This new package also relied on
+
The naming and version numbering selected for this package, however, resulted in conflicts + with the original python-gnupg and since its functions were called in a different manner to + python-gnupg, the release of this package also resulted in a great deal of consternation + when people installed what they thought was an upgrade that subsequently broke the code + relying on it.
+The gnupg package is available under the GNU General Public License version 3.0 (or any + later version).
+ +There have been numerous attempts to add GnuPG support to Python over the years. Some + of the most well known are listed here, along with what differentiates them.
+ +Before we can get to the fun stuff, there are a few matters regarding GPGME's design + which hold true whether you're dealing with the C code directly or these Python + bindings.
+ +Installing the Python bindings is effectively achieved by compiling and installing GPGME + itself.
+Once SWIG is installed with Python and all the dependencies for GPGME are installed you
+ only need to confirm that the version(s) of Python you want the bindings installed for are
+ in your
By default GPGME will attempt to install the bindings for the most recent or highest
+ version number of Python 2 and Python 3 it detects in
For Python 2 it checks for these executables in this order:
For Python 3 it checks for these executables in this order:
Most third-party Python packages and modules are available and distributed through + the Python Package Installer, known as PyPI.
+Due to the nature of what these bindings are and how they work, it is infeasible to install + the GPGME Python bindings in the same way.
+This is because the bindings use SWIG to dynamically generate C bindings against
+
The first part of which is or will be fairly blatantly obvious upon viewing the first + example, but it's worth reiterating anyway. That being that this API is not a + REST API. Nor indeed could it ever be one.
+Most, if not all, Python programmers (and not just Python programmers) know how easy it is + to work with a RESTful API. In fact they've become so popular that many other APIs attempt + to emulate REST-like behaviour as much as they are able. Right down to the use of JSON + formatted output to facilitate the use of their API without having to retrain + developers.
+This API does not do that. It would not be able to do that and also provide access to the + entire C API on which it's built. It does, however, provide a very pythonic interface on top + of the direct bindings and it's this pythonic layer with which this HOWTO deals with.
+ +This package is the origin of these bindings, though they are somewhat different now. For
+ details of when and how the PyME package was folded back into GPGME itself see the
+ Short History document
The PyME package was first released in 2002 and was also the first attempt to implement a
+ low level binding to GPGME. In doing so it provided access to considerably more
+ functionality than either the
The PyME package is only available for Python 2.6 and 2.7.
+Porting the PyME package to Python 3.4 in 2015 is what resulted in it being folded into the + GPGME project and the current bindings are the end result of that effort.
+The PyME package is available under the same dual licensing as GPGME itself: the GNU + General Public License version 2.0 (or any later version) and the GNU Lesser General Public + License version 2.1 (or any later version).
+ +The Python bindings for GPGME provide a higher level means of accessing the complete + feature set of GPGME itself. It also provides a more pythonic means of calling these API + functions.
+The bindings are generated dynamically with SWIG and the copy of
This means that a version of the Python bindings is fundamentally tied to the exact same
+ version of GPGME used to generate that copy of
This is arguably the most popular means of integrating GPG with Python. The package
+ utilises the
The popularity of this package stemmed from its ease of use and capability in providing the + most commonly required features.
+Unfortunately it has been beset by a number of security issues in the past; most of which
+ stemmed from using unsafe methods of accessing the command line via the
+
The python-gnupg package is available under the MIT license.
+ +The GPGME Python bindings only have three requirements:
++
An alternative method of getting a single key via its fingerprint is available + directly within a Context with Context().get_key. This is the preferred method of selecting + a key in order to modify it, sign or certify it and for obtaining relevant data about a + single key as a part of other functions; when verifying a signature made by that key, for + instance.
+By default this method will select public keys, but it can select secret keys as well.
+This first example demonstrates selecting the current key of Werner Koch, which is due to + expire at the end of 2018:
+
+
Whereas this example demonstrates selecting the author's current key with the secret key + word argument set to True:
+
+
It is, of course, quite possible to select expired, disabled and revoked keys with this + function, but only to effectively display information about those keys.
+It is also possible to use both unicode or string literals and byte literals with the + fingerprint when getting a key in this way.
+ +Counting the number of keys in your public keybox (
+
Selecting keys to encrypt to or to sign with will be a common occurrence when working with + GPGMe and the means available for doing so are quite simple.
+They do depend on utilising a Context; however once the data is recorded in another + variable, that Context does not need to be the same one which subsequent operations are + performed.
+The easiest way to select a specific key is by searching for that key's key ID or + fingerprint, preferably the full fingerprint without any spaces in it. A long key ID will + probably be okay, but is not advised and short key IDs are already a problem with some being + generated to match specific patterns. It does not matter whether the pattern is upper or + lower case.
+So this is the best method:
+
+
This is passable and very likely to be common:
+
+
And this is a really bad idea:
+
+
Alternatively it may be that the intention is to create a list of keys which all match a + particular search string. For instance all the addresses at a particular domain, like + this:
+
+
The most frequently called features of any cryptographic library will be the most + fundamental tasks for encryption software. In this section we will look at how to + programmatically encrypt data, decrypt it, sign it and verify signatures.
+ +Though PGP/in-line messages are no longer encouraged in favour of PGP/MIME, there is still + sometimes value in utilising in-line signatures. This is where clear-signed messages or text + is of value.
+
+
In spite of the appearance of a clear-signed message, the data handled by GPGME in signing + it must still be byte literals.
+
+
Decrypting something encrypted to a key in one's secret keyring is fairly straight + forward.
+In this example code, however, preconfiguring either
+
The data available in
The normal or default signing process is essentially the same as is most often + invoked when also encrypting a message or file. So when the encryption component is not + utilised, the result is to produce an encoded and signed output which may or may not be + ASCII armoured and which may or may not also be compressed.
+By default compression will be used unless GnuPG detects that the plaintext is already
+ compressed. ASCII armouring will be determined according to the value of
+
The compression algorithm is selected in much the same way as the symmetric encryption + algorithm or the hash digest algorithm is when multiple keys are involved; from the + preferences saved into the key itself or by comparison with the preferences with all other + keys involved.
+
+
Though everything in this example is accurate, it is more likely that reading the input + data from another file and writing the result to a new file will be performed more like the + way it is done in the next example. Even if the output format is ASCII armoured.
+
+
Detached signatures will often be needed in programmatic uses of GPGME, either for signing + files (e.g. tarballs of code releases) or as a component of message signing (e.g. PGP/MIME + encoded email).
+
+
As with normal signatures, detached signatures are best handled as byte literals, even when + the output is ASCII armoured.
+
+
Encrypting to multiple keys essentially just expands upon the key selection process + and the recipients from the previous examples.
+The following example encrypts a message (
+
All it would take to change the above example to sign the message and also encrypt the
+ message to any configured default keys would be to change the
+
The only keyword arguments requiring modification are those for which the default values
+ are changing. The default value of
If
+
This will attempt to encrypt to all the keys searched for, then remove invalid recipients + if it fails and try again.
+ +Once the the Context is set the main issues with encrypting data is essentially reduced to
+ key selection and the keyword arguments specified in the
+
Those keyword arguments are:
++
+
Though this is even more likely to be used like this; with the plaintext input read from a
+ file, the recipient keys used for encryption regardless of key trust status and the
+ encrypted output also encrypted to any preconfigured keys set in the
+
+
If the
Encrypting is very straight forward. In the first example below the message,
+
By default GPGME and the Python bindings will use the default key configured for the user + invoking the GPGME API. If there is no default key specified and there is more than one + secret key available it may be necessary to specify the key or keys with which to sign + messages and files.
+
+
The signing examples in the following sections include the explicitly designated
+
While it would be possible to enter a key ID or fingerprint here to match a specific key, + it is not possible to enter two fingerprints and match two keys since the patten expects a + string, bytes or None and not a list. A string with two fingerprints won't match any single + key.
+ +The following sections demonstrate how to specify keys to sign with and the types of + signatures which can be made.
+ +Essentially there are two principal methods of verification of a signature. The first + of these is for use with the normal or default signing method and for clear-signed messages. + The second is for use with files and data with detached signatures.
+The following example is intended for use with the default signing method where the file + was not ASCII armoured:
+
+
Whereas this next example, which is almost identical would work with normal ASCII armoured + files and with clear-signed files:
+
+
In both of the previous examples it is also possible to compare the original data that was
+ signed against the signed data in
+
The following two examples, however, deal with detached signatures. With his method of
+ verification the data that was signed does not get returned since it is already being
+ explicitly referenced in the first argument of
+
+
By comparison to creating primary keys and subkeys, adding a new user ID to an existing key
+ is much simpler. The method used to do this is
+
Unsurprisingly the result of this is:
+
+
Since key certification is more frequently referred to as key signing, the method used to
+ perform this function is
The
The
If the
To sign Danger Mouse's key for just the initial user ID with a signature which will last a + little over a month, do this:
+
+
The one thing, aside from GnuPG itself, that GPGME depends on, of course, is the keys + themselves. So it is necessary to be able to generate them and modify them by adding + subkeys, revoking or disabling them, sometimes deleting them and doing the same for user + IDs.
+In the following examples a key will be created for the world's greatest secret agent, + Danger Mouse. Since Danger Mouse is a secret agent he needs to be able to protect + information to SECRET level clearance, so his keys will be 3072-bit keys.
+The pre-configured
+
Generating a primary key uses the
If
+
One thing to note here is the use of setting the
The
The successful generation of the key can be confirmed via the returned
+
+
Alternatively the information can be confirmed using the command line program:
+
+
As with generating keys manually, to preconfigure expanded preferences for the cipher,
+ digest and compression algorithms, the
+
Revoking a user ID is a fairly similar process, except that it uses the
+
+
Adding subkeys to a primary key is fairly similar to creating the primary key with
+ the
In the following example an encryption subkey will be added to the primary key. Since + Danger Mouse is a security conscious secret agent, this subkey will only be valid for about + six months, half the length of the primary key.
+
+
As with the primary key, the results here can be checked with:
+
+
As well as on the command line with:
+
+
There is not yet an easy way to access groups configured in the
+
The following code, however, provides a work-around for obtaining this information in + Python.
+
+
The result of that code is that
The
To use this code as a module use:
+
+