← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/refine-wrong-key-check into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/refine-wrong-key-check into lp:launchpad.

Commit message:
Allow retrieving keys by subkey fingerprint.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/refine-wrong-key-check/+merge/364495
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/refine-wrong-key-check into lp:launchpad.
=== modified file 'lib/lp/services/gpg/handler.py'
--- lib/lp/services/gpg/handler.py	2019-03-13 17:19:50 +0000
+++ lib/lp/services/gpg/handler.py	2019-03-15 11:30:41 +0000
@@ -457,12 +457,7 @@
         if not key.exists_in_local_keyring:
             pubkey = self._getPubKey(fingerprint)
             key = self.importPublicKey(pubkey)
-            # XXX cjwatson 2019-03-13: Remove affordance for 64-bit key IDs
-            # once we're on GnuPG 2.2.7 and GPGME 1.11.0.  See comment in
-            # getVerifiedSignature.
-            if (fingerprint != key.fingerprint and
-                not (len(fingerprint) == 16 and
-                     key.fingerprint.endswith(fingerprint))):
+            if not key.matches(fingerprint):
                 ctx = self._getContext()
                 with gpgme_timeline("delete", key.fingerprint):
                     ctx.delete(key.key)
@@ -658,7 +653,7 @@
             self.keysize, self.algorithm.title, self.fingerprint)
 
     def export(self):
-        """See `PymeKey`."""
+        """See `IPymeKey`."""
         if self.secret:
             # XXX cprov 20081014: gpgme_op_export() only supports public keys.
             # See http://www.fifi.org/cgi-bin/info2www?(gpgme)Exporting+Keys
@@ -674,6 +669,18 @@
 
         return keydata.getvalue()
 
+    def matches(self, fingerprint):
+        """See `IPymeKey`."""
+        for subkey in self.key.subkeys:
+            if fingerprint == subkey.fpr:
+                return True
+            # XXX cjwatson 2019-03-13: Remove affordance for 64-bit key IDs
+            # once we're on GnuPG 2.2.7 and GPGME 1.11.0.  See comment in
+            # getVerifiedSignature.
+            if len(fingerprint) == 16 and subkey.fpr.endswith(fingerprint):
+                return True
+        return False
+
 
 @implementer(IPymeUserId)
 class PymeUserId:

=== modified file 'lib/lp/services/gpg/interfaces.py'
--- lib/lp/services/gpg/interfaces.py	2018-07-22 17:56:11 +0000
+++ lib/lp/services/gpg/interfaces.py	2019-03-15 11:30:41 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2018 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2019 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 __all__ = [
@@ -407,6 +407,9 @@
         :return: a string containing the exported key.
         """
 
+    def matches(fingerprint):
+        """Return True if and only if this fingerprint matches this key."""
+
 
 class IPymeUserId(Interface):
     """pyME user ID"""

=== modified file 'lib/lp/services/gpg/tests/test_gpghandler.py'
--- lib/lp/services/gpg/tests/test_gpghandler.py	2019-03-13 17:19:50 +0000
+++ lib/lp/services/gpg/tests/test_gpghandler.py	2019-03-15 11:30:41 +0000
@@ -193,6 +193,22 @@
             GPGKeyMismatchOnServer, gpghandler.retrieveKey, fingerprint)
         self.assertEqual([], list(gpghandler.localKeys()))
 
+    def test_retrieveKey_allows_subkey(self):
+        # retrieveKey allows retrieving keys by subkey fingerprint.
+        keyserver = self.useFixture(KeyServerTac())
+        primary_fingerprint = "340CA3BB270E2716C9EE0B768E7EB7086C64A8C5"
+        subkey_fingerprint = "A2E916260726EE2BF86501A14244E5A6067595FF"
+        shutil.copy2(
+            test_pubkey_file_from_email("foo.bar@xxxxxxxxxxxxx"),
+            os.path.join(keyserver.root, "0x%s.get" % subkey_fingerprint))
+        gpghandler = getUtility(IGPGHandler)
+        key = gpghandler.retrieveKey(subkey_fingerprint)
+        self.assertEqual(primary_fingerprint, key.fingerprint)
+        self.assertTrue(key.matches(primary_fingerprint))
+        self.assertTrue(key.matches(subkey_fingerprint))
+        self.assertTrue(key.matches(subkey_fingerprint[-16:]))
+        self.assertFalse(key.matches(subkey_fingerprint[:-1] + "0"))
+
     def test_retrieveKey_allows_64bit_key_id(self):
         # In order to support retrieving keys during signature verification,
         # retrieveKey temporarily allows 64-bit key IDs.


Follow ups