summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen McGinnes <ben@adversary.org>2018-06-28 18:33:51 +1000
committerBen McGinnes <ben@adversary.org>2018-06-28 18:33:51 +1000
commitfa1a4e0b25faf995ff1fbadd54917de23da59ebd (patch)
tree413b7cb08a8d2d3bef92282c1e2bd8ccbad15d3c
parent6573eb339a2a657354d3290061b5a2f9e31dab85 (diff)
downloadgpgme-fa1a4e0b25faf995ff1fbadd54917de23da59ebd.tar.gz
docs: python bindings howtoben/export-keys
* Updated official doc (the org-mode file) with the instructions on importing and exporting both public and secret keys.
-rw-r--r--lang/python/docs/GPGMEpythonHOWTOen.org358
1 files changed, 358 insertions, 0 deletions
diff --git a/lang/python/docs/GPGMEpythonHOWTOen.org b/lang/python/docs/GPGMEpythonHOWTOen.org
index 3325c086..6a3f9db0 100644
--- a/lang/python/docs/GPGMEpythonHOWTOen.org
+++ b/lang/python/docs/GPGMEpythonHOWTOen.org
@@ -454,6 +454,364 @@
literals with the fingerprint when getting a key in this way.
+** Importing keys
+ :PROPERTIES:
+ :CUSTOM_ID: howto-import-key
+ :END:
+
+ Importing keys is possible with the =key_import()= 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.
+
+ 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.
+
+ #+begin_src 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
+ #+end_src
+
+ *NOTE:* When searching for a key ID of any length or a fingerprint
+ (without spaces), the SKS servers require the the leading =0x=
+ indicative of hexadecimal be included. Also note that the old short
+ key IDs (e.g. =0xDEADBEEF=) should no longer be used due to the
+ relative ease by which such key IDs can be reproduced, as
+ demonstrated by the Evil32 Project in 2014 (which was subsequently
+ exploited in 2016).
+
+
+** Exporting keys
+ :PROPERTIES:
+ :CUSTOM_ID: howto-export-key
+ :END:
+
+ 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.
+
+
+*** Exporting public keys
+ :PROPERTIES:
+ :CUSTOM_ID: howto-export-public-key
+ :END:
+
+ There are two methods of exporting public keys, both of which are
+ very similar to the other. The default method, =key_export()=,
+ will export a public key or keys matching a specified pattern as
+ normal. The alternative, the =key_export_minimal()= method, will
+ do the same thing except producing a minimised output with extra
+ signatures and third party signatures or certifications removed.
+
+ #+begin_src 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
+ #+end_src
+
+ It is important to note that the result will only return =None=
+ when a pattern has been entered for =logrus=, but it has not
+ matched any keys. When the search pattern itself is set to =None=
+ this triggers the exporting of the entire public keybox.
+
+ #+begin_src 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
+ #+end_src
+
+
+*** Exporting secret keys
+ :PROPERTIES:
+ :CUSTOM_ID: howto-export-secret-key
+ :END:
+
+ Exporting secret keys is, functionally, very similar to exporting
+ public keys; save for the invocation of =pinentry= via =gpg-agent=
+ in order to securely enter the key's passphrase and authorise the
+ export.
+
+ 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.
+
+ #+begin_src 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
+ #+end_src
+
+ 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
+ (=.gpg=) and ASCII armoured (=.asc=) files.
+
+ #+begin_src 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
+ #+end_src
+
+
* Basic Functions
:PROPERTIES:
:CUSTOM_ID: howto-the-basics