diff options
Diffstat (limited to 'lang/python/docs/dita/howto')
-rw-r--r-- | lang/python/docs/dita/howto/part01/docs-source.dita | 11 | ||||
-rw-r--r-- | lang/python/docs/dita/howto/part03/exporting-pubkeys.dita | 120 | ||||
-rw-r--r-- | lang/python/docs/dita/howto/part03/exporting-seckeys.dita | 161 | ||||
-rw-r--r-- | lang/python/docs/dita/howto/part03/exporting.dita | 12 | ||||
-rw-r--r-- | lang/python/docs/dita/howto/part03/importing.dita | 67 | ||||
-rw-r--r-- | lang/python/docs/dita/howto/part04/decryption.dita | 17 | ||||
-rw-r--r-- | lang/python/docs/dita/howto/part06/group-lines.dita | 4 | ||||
-rw-r--r-- | lang/python/docs/dita/howto/version-info.dita | 6 |
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 <<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> |