aboutsummaryrefslogtreecommitdiffstats
path: root/lang/python/docs/dita/howto
diff options
context:
space:
mode:
authorBen McGinnes <[email protected]>2018-06-28 08:02:43 +0000
committerBen McGinnes <[email protected]>2018-06-28 08:02:43 +0000
commitdda54cc851490be045832d5ee0b03be082529d17 (patch)
tree48c6e01a3bb4911e8600ae2f77908d397eff4e88 /lang/python/docs/dita/howto
parentdocs: python bindings howto DITA (diff)
downloadgpgme-dda54cc851490be045832d5ee0b03be082529d17.tar.gz
gpgme-dda54cc851490be045832d5ee0b03be082529d17.zip
python bindings howto: dita version
* Drafts of instructions for exporting public and secret keys ready, along in addition to the code.
Diffstat (limited to 'lang/python/docs/dita/howto')
-rw-r--r--lang/python/docs/dita/howto/part01/docs-source.dita11
-rw-r--r--lang/python/docs/dita/howto/part03/exporting-pubkeys.dita120
-rw-r--r--lang/python/docs/dita/howto/part03/exporting-seckeys.dita161
-rw-r--r--lang/python/docs/dita/howto/part03/exporting.dita12
-rw-r--r--lang/python/docs/dita/howto/part03/importing.dita67
-rw-r--r--lang/python/docs/dita/howto/part04/decryption.dita17
-rw-r--r--lang/python/docs/dita/howto/part06/group-lines.dita4
-rw-r--r--lang/python/docs/dita/howto/version-info.dita6
8 files changed, 388 insertions, 10 deletions
diff --git a/lang/python/docs/dita/howto/part01/docs-source.dita b/lang/python/docs/dita/howto/part01/docs-source.dita
index 8e97a353..7c90b59c 100644
--- a/lang/python/docs/dita/howto/part01/docs-source.dita
+++ b/lang/python/docs/dita/howto/part01/docs-source.dita
@@ -14,15 +14,16 @@
<ol id="ol_k3b_wrx_5db">
<li>A <xref href="https://dev.gnupg.org/T3977" format="html" scope="external">bug</xref>
in either Org-Mode or Babel prevented the more complex examples included in the HOWTO
- from displaying correctly.</li>
+ from displaying correctly while also retaining syntax highlighting.</li>
<li>To demonstrate some of the advantages of DITA XML over existing documentation
production software used in the project (particularly Texinfo and LaTeX).</li>
</ol>
</p>
- <p>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.</p>
+ <p>The XML format definitely supports displaying all the more complex Python code correctly
+ with syntax highlighting, 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.</p>
<p> </p>
</body>
</topic>
diff --git a/lang/python/docs/dita/howto/part03/exporting-pubkeys.dita b/lang/python/docs/dita/howto/part03/exporting-pubkeys.dita
new file mode 100644
index 00000000..8ae4f5bd
--- /dev/null
+++ b/lang/python/docs/dita/howto/part03/exporting-pubkeys.dita
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita xml:lang="en-GB">
+ <topic id="exporting-pubkeys">
+ <title>Exporting Public Keys</title>
+ <body>
+ <p>There are two methods of exporting public keys, both of which are very similar to the
+ other. The default method, <codeph>key_export()</codeph> will export a public key or keys
+ matching a specified pattern as normal. The alternative, the
+ <codeph>key_export_minimal()</codeph> method will do the same thing except producing a
+ minimised output with extra signatures and third party signatures or certifications
+ removed.</p>
+ <p>
+ <codeblock id="export-pubkey-01" outputclass="language-python">import gpg
+import os.path
+import sys
+
+print("""
+This script exports one or more public keys.
+""")
+
+c = gpg.Context(armor=True)
+
+if len(sys.argv) >= 4:
+ keyfile = sys.argv[1]
+ logrus = sys.argv[2]
+ homedir = sys.argv[3]
+elif len(sys.argv) == 3:
+ keyfile = sys.argv[1]
+ logrus = sys.argv[2]
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+elif len(sys.argv) == 2:
+ keyfile = sys.argv[1]
+ logrus = input("Enter the UID matching the key(s) to export: ")
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+else:
+ keyfile = input("Enter the path and filename to save the secret key to: ")
+ logrus = input("Enter the UID matching the key(s) to export: ")
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+
+if homedir.startswith("~"):
+ if os.path.exists(os.path.expanduser(homedir)) is True:
+ c.home_dir = os.path.expanduser(homedir)
+ else:
+ pass
+elif os.path.exists(homedir) is True:
+ c.home_dir = homedir
+else:
+ pass
+
+try:
+ result = c.key_export(pattern=logrus)
+except:
+ result = c.key_export(pattern=None)
+
+if result is not None:
+ with open(keyfile, "wb") as f:
+ f.write(result)
+else:
+ pass
+</codeblock>
+ </p>
+ <p>It is important to note that the <codeph>result</codeph> will only return
+ <codeph>None</codeph> when a pattern has been entered for <varname>logrus</varname>, but
+ it has not matched any keys. When the search pattern itself is set to <codeph>None</codeph>
+ this triggers the exporting of the entire public keybox.</p>
+ <p>
+ <codeblock id="export-pubkey-02" outputclass="language-python">import gpg
+import os.path
+import sys
+
+print("""
+This script exports one or more public keys in minimised form.
+""")
+
+c = gpg.Context(armor=True)
+
+if len(sys.argv) >= 4:
+ keyfile = sys.argv[1]
+ logrus = sys.argv[2]
+ homedir = sys.argv[3]
+elif len(sys.argv) == 3:
+ keyfile = sys.argv[1]
+ logrus = sys.argv[2]
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+elif len(sys.argv) == 2:
+ keyfile = sys.argv[1]
+ logrus = input("Enter the UID matching the key(s) to export: ")
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+else:
+ keyfile = input("Enter the path and filename to save the secret key to: ")
+ logrus = input("Enter the UID matching the key(s) to export: ")
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+
+if homedir.startswith("~"):
+ if os.path.exists(os.path.expanduser(homedir)) is True:
+ c.home_dir = os.path.expanduser(homedir)
+ else:
+ pass
+elif os.path.exists(homedir) is True:
+ c.home_dir = homedir
+else:
+ pass
+
+try:
+ result = c.key_export_minimal(pattern=logrus)
+except:
+ result = c.key_export_minimal(pattern=None)
+
+if result is not None:
+ with open(keyfile, "wb") as f:
+ f.write(result)
+else:
+ pass
+</codeblock>
+ </p>
+ <p/>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part03/exporting-seckeys.dita b/lang/python/docs/dita/howto/part03/exporting-seckeys.dita
new file mode 100644
index 00000000..9093aa08
--- /dev/null
+++ b/lang/python/docs/dita/howto/part03/exporting-seckeys.dita
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita xml:lang="en-GB">
+ <topic id="exporting-seckeys">
+ <title>Exporting Secret Keys</title>
+ <body>
+ <p>Exporting secret keys is, functionally, very similar to exporting public keys; save for the
+ invocation of <cmdname>pinentry</cmdname> via <cmdname>gpg-agent</cmdname> in order to
+ securely enter the key's passphrase and authorise the export.</p>
+ <p>The following example exports the secret key to a file which is then set with the same
+ permissions as the output files created by the command line secret key export options.</p>
+ <p>
+ <codeblock id="export-seckey-01" outputclass="language-python">import gpg
+import os
+import os.path
+import sys
+
+print("""
+This script exports one or more secret keys.
+
+The gpg-agent and pinentry are invoked to authorise the export.
+""")
+
+c = gpg.Context(armor=True)
+
+if len(sys.argv) >= 4:
+ keyfile = sys.argv[1]
+ logrus = sys.argv[2]
+ homedir = sys.argv[3]
+elif len(sys.argv) == 3:
+ keyfile = sys.argv[1]
+ logrus = sys.argv[2]
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+elif len(sys.argv) == 2:
+ keyfile = sys.argv[1]
+ logrus = input("Enter the UID matching the secret key(s) to export: ")
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+else:
+ keyfile = input("Enter the path and filename to save the secret key to: ")
+ logrus = input("Enter the UID matching the secret key(s) to export: ")
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+
+if homedir.startswith("~"):
+ if os.path.exists(os.path.expanduser(homedir)) is True:
+ c.home_dir = os.path.expanduser(homedir)
+ else:
+ pass
+elif os.path.exists(homedir) is True:
+ c.home_dir = homedir
+else:
+ pass
+
+try:
+ result = c.key_export_secret(pattern=logrus)
+except:
+ result = c.key_export_secret(pattern=None)
+
+if result is not None:
+ with open(keyfile, "wb") as f:
+ f.write(result)
+ os.chmod(keyfile, 0o600)
+else:
+ pass
+</codeblock>
+ </p>
+ <p>Alternatively the approach of the following script can be used. This longer example saves
+ the exported secret key(s) in files in the GnuPG home directory, in addition to setting the
+ file permissions as only readable and writable by the user. It also exports the secret
+ key(s) twice in order to output both GPG binary (<codeph>.gpg</codeph>) and ASCII armoured
+ (<codeph>.asc</codeph>) files.</p>
+ <p>
+ <codeblock id="export-seckey-02" outputclass="language-python">import gpg
+import os
+import os.path
+import subprocess
+import sys
+
+print("""
+This script exports one or more secret keys as both ASCII armored and binary
+file formats, saved in files within the user's GPG home directory.
+
+The gpg-agent and pinentry are invoked to authorise the export.
+""")
+
+if sys.platform == "win32":
+ gpgconfcmd = "gpgconf.exe --list-dirs homedir"
+else:
+ gpgconfcmd = "gpgconf --list-dirs homedir"
+
+a = gpg.Context(armor=True)
+b = gpg.Context()
+c = gpg.Context()
+
+if len(sys.argv) >= 4:
+ keyfile = sys.argv[1]
+ logrus = sys.argv[2]
+ homedir = sys.argv[3]
+elif len(sys.argv) == 3:
+ keyfile = sys.argv[1]
+ logrus = sys.argv[2]
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+elif len(sys.argv) == 2:
+ keyfile = sys.argv[1]
+ logrus = input("Enter the UID matching the secret key(s) to export: ")
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+else:
+ keyfile = input("Enter the filename to save the secret key to: ")
+ logrus = input("Enter the UID matching the secret key(s) to export: ")
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+
+if homedir.startswith("~"):
+ if os.path.exists(os.path.expanduser(homedir)) is True:
+ c.home_dir = os.path.expanduser(homedir)
+ else:
+ pass
+elif os.path.exists(homedir) is True:
+ c.home_dir = homedir
+else:
+ pass
+
+if c.home_dir is not None:
+ if c.home_dir.endswith("/"):
+ gpgfile = "{0}{1}.gpg".format(c.home_dir, keyfile)
+ ascfile = "{0}{1}.asc".format(c.home_dir, keyfile)
+ else:
+ gpgfile = "{0}/{1}.gpg".format(c.home_dir, keyfile)
+ ascfile = "{0}/{1}.asc".format(c.home_dir, keyfile)
+else:
+ if os.path.exists(os.environ["GNUPGHOME"]) is True:
+ hd = os.environ["GNUPGHOME"]
+ else:
+ hd = subprocess.getoutput(gpgconfcmd)
+ gpgfile = "{0}/{1}.gpg".format(hd, keyfile)
+ ascfile = "{0}/{1}.asc".format(hd, keyfile)
+
+try:
+ a_result = a.key_export_secret(pattern=logrus)
+ b_result = b.key_export_secret(pattern=logrus)
+except:
+ a_result = a.key_export_secret(pattern=None)
+ b_result = b.key_export_secret(pattern=None)
+
+if a_result is not None:
+ with open(ascfile, "wb") as f:
+ f.write(a_result)
+ os.chmod(ascfile, 0o600)
+else:
+ pass
+
+if b_result is not None:
+ with open(gpgfile, "wb") as f:
+ f.write(b_result)
+ os.chmod(gpgfile, 0o600)
+else:
+ pass
+</codeblock>
+ </p>
+ <p/>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part03/exporting.dita b/lang/python/docs/dita/howto/part03/exporting.dita
new file mode 100644
index 00000000..8c054af0
--- /dev/null
+++ b/lang/python/docs/dita/howto/part03/exporting.dita
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita xml:lang="en-GB">
+ <topic id="exporting-keys">
+ <title>Exporting Keys</title>
+ <body>
+ <p>Exporting keys remains a reasonably simple task, but has been separated into three
+ different functions for the OpenPGP cryptographic engine. Two of those functions are for
+ exporting public keys and the third is for exporting secret keys.</p>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part03/importing.dita b/lang/python/docs/dita/howto/part03/importing.dita
new file mode 100644
index 00000000..267eb94e
--- /dev/null
+++ b/lang/python/docs/dita/howto/part03/importing.dita
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE dita PUBLIC "-//OASIS//DTD DITA Composite//EN" "ditabase.dtd">
+<dita xml:lang="en-GB">
+ <topic id="importing-keys">
+ <title>Importing keys</title>
+ <body>
+ <p>Importing keys is possible with the <codeph>key_import()</codeph> method and takes one
+ argument which is a bytes literal object containing either the binary or ASCII armoured key
+ data for one or more keys.</p>
+ <p>The following example retrieves one or more keys from the SKS keyservers via the web using
+ the requests module. Since requests returns the content as a bytes literal object, we can
+ then use that directly to import the resulting data into our keybox.</p>
+ <p>
+ <codeblock id="key-import-01" outputclass="language-python">import gpg
+import os.path
+import requests
+
+c = gpg.Context()
+url = "https://sks-keyservers.net/pks/lookup"
+pattern = input("Enter the pattern to search for key or user IDs: ")
+payload = { "op": "get", "search": pattern }
+
+r = requests.get(url, verify=True, params=payload)
+result = c.key_import(r.content)
+
+if result is not None and hasattr(result, "considered") is False:
+ print(result)
+elif result is not None and hasattr(result, "considered") is True:
+ num_keys = len(result.imports)
+ new_revs = result.new_revocations
+ new_sigs = result.new_signatures
+ new_subs = result.new_sub_keys
+ new_uids = result.new_user_ids
+ new_scrt = result.secret_imported
+ nochange = result.unchanged
+ print("""
+The total number of keys considered for import was: {0}
+
+ Number of keys revoked: {1}
+ Number of new signatures: {2}
+ Number of new subkeys: {3}
+ Number of new user IDs: {4}
+Number of new secret keys: {5}
+ Number of unchanged keys: {6}
+
+The key IDs for all considered keys were:
+""".format(num_keys, new_revs, new_sigs, new_subs, new_uids, new_scrt,
+ nochange))
+ for i in range(num_keys):
+ print(result.imports[i].fpr)
+ print("")
+else:
+ pass
+</codeblock>
+ </p>
+ <p>
+ <note>When searching for a key ID of any length or a fingerprint (without spaces), the SKS
+ servers require the the leading <codeph>0x</codeph> indicative of hexadecimal be included.
+ Also note that the old short key IDs (e.g. <codeph>0xDEADBEEF</codeph>) should no longer
+ be used due to the relative ease by which such key IDs can be reproduced, as demonstrated
+ by the <xref href="https://evil32.com/" format="html" scope="external">Evil32
+ Project</xref> in 2014 (which was subsequently exploited in 2016).</note>
+ </p>
+ <p/>
+ </body>
+ </topic>
+</dita>
diff --git a/lang/python/docs/dita/howto/part04/decryption.dita b/lang/python/docs/dita/howto/part04/decryption.dita
index 41a4650e..bb8c3680 100644
--- a/lang/python/docs/dita/howto/part04/decryption.dita
+++ b/lang/python/docs/dita/howto/part04/decryption.dita
@@ -30,9 +30,20 @@ else:
pass
</codeblock>
</p>
- <p>The data available in <codeph>plaintext</codeph> in this example is the decrypted content
- as a byte object, the recipient key IDs and algorithms in <codeph>result</codeph> and the
- results of verifying any signatures of the data in <codeph>verify_result</codeph>.</p>
+ <p>The data available in <codeph>plaintext</codeph> following a successful decryption in this
+ example is the decrypted content as a byte object, the recipient key IDs and algorithms in
+ <codeph>result</codeph> and the results of verifying any signatures of the data in
+ <codeph>verify_result</codeph>.</p>
+ <p>
+ <note>The graceful handling of <codeph>GPGMEError</codeph> with the try/except statement is
+ to handle the decryption error message produced if the file <codeph>ciphertext</codeph>,
+ and thus <codeph>cfile</codeph>, are encrypted with deprecated and insecure methods.
+ Particularly without MDC integrity checks or utilising deprecated encryption algorithms.
+ Messages and files encrypted with these are not decrypted with GPGME at all and any user
+ requiring archival access will need to access it manually with pre-GnuPG 2.3 versions of
+ the software which meets the requirements of the specific use case.</note>
+ </p>
+ <p/>
</body>
</topic>
</dita>
diff --git a/lang/python/docs/dita/howto/part06/group-lines.dita b/lang/python/docs/dita/howto/part06/group-lines.dita
index f4aca74c..1dbfc97a 100644
--- a/lang/python/docs/dita/howto/part06/group-lines.dita
+++ b/lang/python/docs/dita/howto/part06/group-lines.dita
@@ -44,6 +44,10 @@ for i in range(len(group_lists)):
<p>
<codeblock id="groups-2" outputclass="language-python">from groups import group_lists</codeblock>
</p>
+ <p>A demonstration of using the <filepath>groups.py</filepath> module is also available in
+ the form of the executable <cmdname>mutt-groups.py</cmdname> script. This second script
+ reads all the group entries in a user's <filepath>gpg.conf</filepath> file and converts them
+ into crypt-hooks suitable for use with the Mutt and Neomutt mail clients.</p>
</body>
</topic>
</dita>
diff --git a/lang/python/docs/dita/howto/version-info.dita b/lang/python/docs/dita/howto/version-info.dita
index 67768204..f9bb42aa 100644
--- a/lang/python/docs/dita/howto/version-info.dita
+++ b/lang/python/docs/dita/howto/version-info.dita
@@ -4,10 +4,12 @@
<topic id="topic_vnz_nn2_vdb">
<title>Documentation Version</title>
<body>
- <p><b>Version:</b> 0.1.1</p>
+ <p><b>Version:</b> 0.1.2-DRAFT</p>
<p><b>Author:</b> Ben McGinnes &lt;<xref href="mailto:[email protected]" format="html"
scope="external">[email protected]</xref>></p>
- <p><b>Author GPG Key ID:</b> DB4724E6FA4286C92B4E55C4321E4E2373590E5D</p>
+ <p><b>Author GPG Key ID:</b>
+ <xref href="http://files.au.adversary.org/crypto/ben-key.asc" format="text" scope="external"
+ >DB4724E6FA4286C92B4E55C4321E4E2373590E5D</xref></p>
<p><b>Language:</b> Australian English, British English</p>
</body>
</topic>