[elbe-devel] [PATCH v3 2/2] Replace gpgme with maintained gpg module

bage at linutronix.de bage at linutronix.de
Sun Feb 17 20:00:32 CET 2019


From: Bastian Germann <bage at linutronix.de>

The pygpgme project is abandoned for years and not
available in the upcoming Debian buster.

Replace pygpgme with the official gpgme Python wrapper
from GnuPG that is available as Debian's python-gpg.
Replace the package references in README and the Debian
build.

With this change, elbe can be installed on Debian buster.
This closes issue #192.

Signed-off-by: Bastian Germann <bage at linutronix.de>
---
 README.adoc              |  2 +-
 debian/control           |  2 --
 elbepack/debinstaller.py | 12 ++++++---
 elbepack/egpg.py         | 63 +++++++++++++++++++++++++-----------------------
 elbepack/finetuning.py   | 12 ++++-----
 5 files changed, 47 insertions(+), 44 deletions(-)

diff --git a/README.adoc b/README.adoc
index 397ba310..a28945dd 100644
--- a/README.adoc
+++ b/README.adoc
@@ -13,7 +13,7 @@ Software Dependencies
 ---------------------
 If using ELBE from git repository directly, you'll need following packages installed:
 
-    apt install python python-debian python-mako python-lxml python-apt python-gpgme python-pyme python-suds python-libvirt qemu-utils qemu-kvm p7zip-full make
+    apt install python python-debian python-mako python-lxml python-apt python-gpg python-suds python-libvirt qemu-utils qemu-kvm p7zip-full make
 
 
 Crash Course
diff --git a/debian/control b/debian/control
index a52a1305..f156e300 100644
--- a/debian/control
+++ b/debian/control
@@ -57,7 +57,6 @@ Depends: ${misc:Depends},
   python (>= 2.7~),
   python-lxml,
   python-apt,
-  python-gpgme,
   python-pyme|python-gpg,
   python-libvirt,
   wget,
@@ -73,7 +72,6 @@ Depends: ${misc:Depends},
   python3,
   python3-lxml,
   python3-apt,
-  python3-gpgme,
   python3-gpg,
   python3-libvirt,
   wget,
diff --git a/elbepack/debinstaller.py b/elbepack/debinstaller.py
index 1a46b353..58670e32 100644
--- a/elbepack/debinstaller.py
+++ b/elbepack/debinstaller.py
@@ -23,8 +23,9 @@ except ImportError:
     import urllib2
     urlopen = urllib2.urlopen
 
+import gpg
+
 from shutil import copyfileobj, copyfile
-from gpgme import Context
 
 from elbepack.filesystem import TmpdirFilesystem
 from elbepack.egpg import OverallStatus, check_signature
@@ -127,7 +128,7 @@ def download_release(tmp, base_url):
     # setup gpg context, for verifying
     # the Release.gpg signature.
     os.environ['GNUPGHOME'] = tmp.fname('/')
-    ctx = Context()
+    ctx = gpg.Context()
 
     # download the Relase file to a tmp file,
     # because we need it 2 times
@@ -144,14 +145,17 @@ def download_release(tmp, base_url):
             overall_status = OverallStatus()
 
             # verify detached signature
-            sigs = ctx.verify(sig, signed, None)
+            _, vres = ctx.verify(signed, sig.read())
 
-            for s in sigs:
+            for s in vres.signatures:
                 status = check_signature(ctx, s)
                 overall_status.add(status)
 
             if overall_status.to_exitcode():
                 raise InvalidSignature('Failed to verify Release file')
+
+    except gpg.errors.BadSignatures:
+            raise InvalidSignature('Failed to verify Release file')
     finally:
         sig.close()
 
diff --git a/elbepack/egpg.py b/elbepack/egpg.py
index c56f22e5..40cd54d9 100644
--- a/elbepack/egpg.py
+++ b/elbepack/egpg.py
@@ -9,7 +9,7 @@ from __future__ import print_function
 
 import os
 
-import gpgme
+import gpg
 
 from elbepack.filesystem import hostfs
 
@@ -34,7 +34,7 @@ class OverallStatus(object):
         self.sig_expired = False
         self.key_revoked = False
         self.key_missing = False
-        self.gpgme_error = False
+        self.gpg_error = False
 
     def add(self, to_add):
         self.invalid = self.invalid or to_add.invalid
@@ -42,10 +42,10 @@ class OverallStatus(object):
         self.sig_expired = self.sig_expired or to_add.sig_expired
         self.key_revoked = self.key_revoked or to_add.key_revoked
         self.key_missing = self.key_missing or to_add.key_missing
-        self.gpgme_error = self.gpgme_error or to_add.gpgme_error
+        self.gpg_error = self.gpg_error or to_add.gpg_error
 
     def to_exitcode(self):
-        if self.gpgme_error:    # critical GPG error
+        if self.gpg_error:      # critical GPG error
             return 20
         if self.invalid:        # invalid signature
             return 1
@@ -61,7 +61,8 @@ class OverallStatus(object):
 def check_signature(ctx, sig):
     status = OverallStatus()
 
-    if sig.summary & gpgme.SIGSUM_KEY_MISSING:
+    sigsum = gpg.constants.sigsum
+    if sig.summary & sigsum.KEY_MISSING:
         print("Signature with unknown key: %s" % sig.fpr)
         status.key_missing = True
         return status
@@ -69,7 +70,7 @@ def check_signature(ctx, sig):
     # there should be a key
     key = ctx.get_key(sig.fpr)
     print("%s <%s> (%s):" % (key.uids[0].name, key.uids[0].email, sig.fpr))
-    if sig.summary & gpgme.SIGSUM_VALID == gpgme.SIGSUM_VALID:
+    if sig.summary & sigsum.VALID == sigsum.VALID:
         # signature fully valid and trusted
         print("VALID (Trusted)")
         return status
@@ -79,30 +80,30 @@ def check_signature(ctx, sig):
         # Signature is valid, but the key is not ultimately trusted,
         # see: http://www.gossamer-threads.com/lists/gnupg/users/52350
         print("VALID (Untrusted).")
-    if sig.summary & gpgme.SIGSUM_SIG_EXPIRED == gpgme.SIGSUM_SIG_EXPIRED:
+    if sig.summary & sigsum.SIG_EXPIRED == sigsum.SIG_EXPIRED:
         print("SIGNATURE EXPIRED!")
         status.sig_expired = True
-    if sig.summary & gpgme.SIGSUM_KEY_EXPIRED == gpgme.SIGSUM_KEY_EXPIRED:
+    if sig.summary & sigsum.KEY_EXPIRED == sigsum.KEY_EXPIRED:
         print("KEY EXPIRED!")
         status.key_expired = True
-    if sig.summary & gpgme.SIGSUM_KEY_REVOKED == gpgme.SIGSUM_KEY_REVOKED:
+    if sig.summary & sigsum.KEY_REVOKED == sigsum.KEY_REVOKED:
         print("KEY REVOKED!")
         status.key_revoked = True
-    if sig.summary & gpgme.SIGSUM_RED == gpgme.SIGSUM_RED:
+    if sig.summary & sigsum.RED == sigsum.RED:
         print("INVALID SIGNATURE!")
         status.invalid = True
-    if sig.summary & gpgme.SIGSUM_CRL_MISSING == gpgme.SIGSUM_CRL_MISSING:
+    if sig.summary & sigsum.CRL_MISSING == sigsum.CRL_MISSING:
         print("CRL MISSING!")
-        status.gpgme_error = True
-    if sig.summary & gpgme.SIGSUM_CRL_TOO_OLD == gpgme.SIGSUM_CRL_TOO_OLD:
+        status.gpg_error = True
+    if sig.summary & sigsum.CRL_TOO_OLD == sigsum.CRL_TOO_OLD:
         print("CRL TOO OLD!")
-        status.gpgme_error = True
-    if sig.summary & gpgme.SIGSUM_BAD_POLICY == gpgme.SIGSUM_BAD_POLICY:
+        status.gpg_error = True
+    if sig.summary & sigsum.BAD_POLICY == sigsum.BAD_POLICY:
         print("UNMET POLICY REQUIREMENT!")
-        status.gpgme_error = True
-    if sig.summary & gpgme.SIGSUM_SYS_ERROR == gpgme.SIGSUM_SYS_ERROR:
+        status.gpg_error = True
+    if sig.summary & sigsum.SYS_ERROR == sigsum.SYS_ERROR:
         print("SYSTEM ERROR!'")
-        status.gpgme_error = True
+        status.gpg_error = True
 
     return status
 
@@ -116,7 +117,7 @@ def unsign_file(fname):
     outfilename = fname[:len(fname) - 4]
 
     os.environ['GNUPGHOME'] = "/var/cache/elbe/gnupg"
-    ctx = gpgme.Context()
+    ctx = gpg.Context()
     ctx.armor = False
 
     try:
@@ -126,9 +127,9 @@ def unsign_file(fname):
             with open(outfilename, 'w') as outfile:
 
                 # obtain signature and write unsigned file
-                sigs = ctx.verify(infile, None, outfile)
+                _, vres = ctx.verify(infile, None, outfile)
 
-                for sig in sigs:
+                for sig in vres.signatures:
                     status = check_signature(ctx, sig)
                     overall_status.add(status)
 
@@ -148,19 +149,19 @@ def unsign_file(fname):
 def sign(infile, outfile, fingerprint):
 
     os.environ['GNUPGHOME'] = "/var/cache/elbe/gnupg"
-    ctx = gpgme.Context()
+    ctx = gpg.Context()
     key = None
 
     try:
         key = ctx.get_key(fingerprint)
-    except gpgme.GpgmeError as ex:
+    except Exception as ex:
         print("no key with fingerprint %s: %s" % (fingerprint, ex.message))
 
     ctx.signers = [key]
     ctx.armor = False
 
     try:
-        ctx.sign(infile, outfile, gpgme.SIG_MODE_NORMAL)
+        ctx.sign(infile.read(), outfile)
     except Exception as ex:
         print("Error signing file %s" % ex.message)
 
@@ -178,30 +179,32 @@ def sign_file(fname, fingerprint):
 
 def get_fingerprints():
     os.environ['GNUPGHOME'] = "/var/cache/elbe/gnupg"
-    ctx = gpgme.Context()
+    ctx = gpg.Context()
     keys = ctx.keylist()
     fingerprints = []
     for k in keys:
-        fingerprints.append(k.subkeys[0].fpr)
+        fingerprints.append(k.fpr)
     return fingerprints
 
 
 def generate_elbe_internal_key():
     hostfs.mkdir_p("/var/cache/elbe/gnupg")
     os.environ['GNUPGHOME'] = "/var/cache/elbe/gnupg"
-    ctx = gpgme.Context()
-    key = ctx.genkey(elbe_internal_key_param)
+    ctx = gpg.Context()
+    ctx.op_genkey(elbe_internal_key_param, None, None)
+    key = ctx.op_genkey_result()
 
     return key.fpr
 
 
 def export_key(fingerprint, outfile):
     os.environ['GNUPGHOME'] = "/var/cache/elbe/gnupg"
-    ctx = gpgme.Context()
+    ctx = gpg.Context()
     ctx.armor = True
 
     try:
-        ctx.export(fingerprint, outfile)
+        key = ctx.key_export(fingerprint)
+        outfile.write(key)
     except Exception:
         print("Error exporting key %s" % (fingerprint))
 
diff --git a/elbepack/finetuning.py b/elbepack/finetuning.py
index 0d9a2824..70b9793b 100644
--- a/elbepack/finetuning.py
+++ b/elbepack/finetuning.py
@@ -11,9 +11,8 @@ from __future__ import print_function
 import os
 
 from shutil import rmtree
-from io import BytesIO
 
-import gpgme
+import gpg
 
 from apt.package import FetchError
 
@@ -421,14 +420,13 @@ class UpdatedAction(FinetuningAction):
             log.printo("transfer gpg key to target: " + fp)
 
             os.environ['GNUPGHOME'] = "/var/cache/elbe/gnupg"
-            key = BytesIO()
-            ctx = gpgme.Context()
+            ctx = gpg.Context()
             ctx.armor = True
-            ctx.export(fp, key)
+            key = ctx.key_export(fp)
 
-            log.printo(str(key.getvalue()))
+            log.printo(key)
             with open((target.path + '/pub.key'), 'wb') as tkey:
-                tkey.write(key.getvalue())
+                tkey.write(key)
 
             target.mkdir_p("/var/cache/elbe/gnupg", mode=0o700)
             with target:
-- 
2.11.0




More information about the elbe-devel mailing list