summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen McGinnes <ben@adversary.org>2018-06-07 09:46:56 +1000
committerBen McGinnes <ben@adversary.org>2018-06-07 09:46:56 +1000
commit167847f1bcfb1b573bd40fe897f39d4ee4167176 (patch)
treef9b8ef6c5ef3db191c5183a4806041f32e52de57
parent2c4c5692472f5870f907c2c3f01870879cb0c34b (diff)
downloadgpgme-ben/key-import.tar.gz
python bindings: import keysben/key-import
* Adapted from prior submissions by Tobias Mueller and Jacob Adams. * key_import function added to gpg.core.Context(). * Two example scripts added to to examples/howto: import-key-file.py imports keys from a local file and import-keys.py accesses the SKS keyserver pool using the requests module to search for keys (includes check for key IDs which may not include the leading 0x). * Added documentation demonstrating the use of the key_import() function with a large number of keys matching one domain (eff.org; the example shows how EFF staff are following their own advice issued last month).
-rw-r--r--lang/python/docs/GPGMEpythonHOWTOen.org79
-rwxr-xr-xlang/python/examples/howto/import-key-file.py70
-rwxr-xr-xlang/python/examples/howto/import-keys.py78
-rw-r--r--lang/python/src/core.py22
4 files changed, 249 insertions, 0 deletions
diff --git a/lang/python/docs/GPGMEpythonHOWTOen.org b/lang/python/docs/GPGMEpythonHOWTOen.org
index 3325c086..31929fa3 100644
--- a/lang/python/docs/GPGMEpythonHOWTOen.org
+++ b/lang/python/docs/GPGMEpythonHOWTOen.org
@@ -454,6 +454,85 @@
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.
+
+ In the following example a key will be retrieved 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. In order to
+ demonstrate multiple imports this example searches for all the keys
+ of users at a particular domain name; in this case the EFF.
+
+ #+begin_src python
+ import gpg
+ import os.path
+ import requests
+
+ c = gpg.Context()
+
+ homedir = input("Enter the GPG configuration directory path (optional): ")
+ pattern = input("The pattern to search for in key or user IDs: ")
+ url = "https://sks-keyservers.net/pks/lookup"
+ payload = { "op": "get", "search": pattern }
+
+ 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
+
+ r = requests.get(url, verify=True, params=payload)
+ incoming = c.key_import(r.content)
+
+ summary = """
+ Total number of keys: {0}
+ Total number imported: {1}
+ Number of version 3 keys ignored: {2}
+
+ Number of imported key objects or updates: {3}
+ Number of unchanged keys: {4}
+ Number of new signatures: {5}
+ Number of revoked keys: {6}
+ """.format(incoming.considered, len(incoming.imports),
+ incoming.skipped_v3_keys, incoming.imported, incoming.unchanged,
+ incoming.new_signatures, incoming.new_revocations)
+
+ print(summary)
+ #+end_src
+
+ The resulting output in that case, where the search pattern entered
+ was =@eff.org= was:
+
+ #+begin_src shell
+ Total number of keys: 272
+ Total number imported: 249
+ Number of version 3 keys ignored: 23
+
+ Number of imported key objects or updates: 180
+ Number of unchanged keys: 66
+ Number of new signatures: 7
+ Number of revoked keys: 0
+ #+end_src
+
+ The examples for this document in =lang/python/examples/howto/ now
+ include to variations of this; one for searching the SKS keyserver
+ pool and the other for importing from a local file.
+
+ The example above and the corresponding executable script included
+ in the examples requires Kenneth Reitz's excellent [[http://docs.python-requests.org/en/master/][Requests module]].
+
+
* Basic Functions
:PROPERTIES:
:CUSTOM_ID: howto-the-basics
diff --git a/lang/python/examples/howto/import-key-file.py b/lang/python/examples/howto/import-key-file.py
new file mode 100755
index 00000000..26ec5242
--- /dev/null
+++ b/lang/python/examples/howto/import-key-file.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, division, unicode_literals
+
+# Copyright (C) 2018 Ben McGinnes <ben@gnupg.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License and the GNU
+# Lesser General Public Licensefor more details.
+#
+# You should have received a copy of the GNU General Public License and the GNU
+# Lesser General Public along with this program; if not, see
+# <http://www.gnu.org/licenses/>.
+
+import gpg
+import os.path
+
+print("""
+This script imports a key or keys matching a pattern from the SKS keyserver
+pool.
+""")
+
+c = gpg.Context()
+
+homedir = input("Enter the GPG configuration directory path (optional): ")
+keyfile = input("Enter the path and filename to the file of key(s): ")
+
+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
+
+with open(keyfile, "rb") as f:
+ kdata = f.read()
+
+incoming = c.key_import(kdata)
+
+summary = """
+Total number of keys: {0}
+Total number imported: {1}
+Number of version 3 keys ignored: {2}
+
+Number of imported key objects or updates: {3}
+Number of unchanged keys: {4}
+Number of new signatures: {5}
+Number of revoked keys: {6}
+""".format(incoming.considered, len(incoming.imports),
+ incoming.skipped_v3_keys, incoming.imported, incoming.unchanged,
+ incoming.new_signatures, incoming.new_revocations)
+
+print(summary)
+
+# EOF
diff --git a/lang/python/examples/howto/import-keys.py b/lang/python/examples/howto/import-keys.py
new file mode 100755
index 00000000..455b8e0c
--- /dev/null
+++ b/lang/python/examples/howto/import-keys.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import, division, unicode_literals
+
+# Copyright (C) 2018 Ben McGinnes <ben@gnupg.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation; either version 2.1 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License and the GNU
+# Lesser General Public Licensefor more details.
+#
+# You should have received a copy of the GNU General Public License and the GNU
+# Lesser General Public along with this program; if not, see
+# <http://www.gnu.org/licenses/>.
+
+import gpg
+import os.path
+import requests
+
+print("""
+This script imports a key or keys matching a pattern from the SKS keyserver
+pool.
+
+Uses the requests module.
+""")
+
+c = gpg.Context()
+
+homedir = input("Enter the GPG configuration directory path (optional): ")
+pattern = input("The pattern to search for in key or user IDs: ")
+url = "https://sks-keyservers.net/pks/lookup"
+payload = { "op": "get", "search": pattern }
+hexload = { "op": "get", "search": "0x{0}".format(pattern) }
+
+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
+
+resp = requests.get(url, verify=True, params=payload)
+if resp.ok is False:
+ rhex = requests.get(url, verify=True, params=hexload)
+ incoming = c.key_import(rhex.content)
+else:
+ incoming = c.key_import(resp.content)
+
+summary = """
+Total number of keys: {0}
+Total number imported: {1}
+Number of version 3 keys ignored: {2}
+
+Number of imported key objects or updates: {3}
+Number of unchanged keys: {4}
+Number of new signatures: {5}
+Number of revoked keys: {6}
+""".format(incoming.considered, len(incoming.imports),
+ incoming.skipped_v3_keys, incoming.imported, incoming.unchanged,
+ incoming.new_signatures, incoming.new_revocations)
+
+print(summary)
+
+# EOF
diff --git a/lang/python/src/core.py b/lang/python/src/core.py
index bd95d231..10db3d69 100644
--- a/lang/python/src/core.py
+++ b/lang/python/src/core.py
@@ -509,6 +509,28 @@ class Context(GpgmeWrapper):
return results
+ def key_import(self, keydata):
+ """Importing keys
+
+ Arguments:
+ keydata -- Binary or ASCII armored key(s) to be imported
+
+ Returns
+ -- an object describing the results of keys imported or
+ updated
+
+ Raises:
+ GPGMEError -- as signaled by the underlying library
+ """
+ if keydata is not None:
+ try:
+ self.op_import(keydata)
+ result = self.op_import_result()
+ except GPGMEError as e:
+ result = e
+ else:
+ result = "No keys found."
+
def keylist(self, pattern=None, secret=False,
mode=constants.keylist.mode.LOCAL,
source=None):