python: stop raising BadSignatures from decrypt(verify=True) dkg/fix-T4276
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Fri, 3 May 2019 03:28:11 +0000 (23:28 -0400)
committerDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Fri, 3 May 2019 03:28:11 +0000 (23:28 -0400)
* src/core.py (decrypt): filter out signatures with errors from the
returned verify_result, but avoid raising BadSignatures
* tests/t-decrypt-verify.py: ensure that only a single signature is
returned when evaluating cipher-3.asc, since the other signature is
unknown.

--

This change preserves the invariant that decrypt() only ever returns
valid signatures in the verify_result, but it avoids unnecessary
errors in the face of the presence of an additional bad signature.

GnuPG-bug-id: 4276
Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
lang/python/src/core.py
lang/python/tests/t-decrypt-verify.py

index c096ee7..11af702 100644 (file)
@@ -342,10 +342,12 @@ class Context(GpgmeWrapper):
 
         Decrypt the given ciphertext and verify any signatures.  If
         VERIFY is an iterable of keys, the ciphertext must be signed
-        by all those keys, otherwise an error is raised.  Note: if
-        VERIFY is an empty iterable, that is treated the same as
-        passing verify=True (that is, do verify signatures, but no
-        specific keys are required).
+        by all those keys, otherwise a MissingSignatures error is
+        raised.  Note: if VERIFY is an empty iterable, that is treated
+        the same as passing verify=True (that is, verify signatures
+        and return data about any valid signatures found, but no
+        signatures are required and no MissingSignatures error will be
+        raised).
 
         If the ciphertext is symmetrically encrypted using a
         passphrase, that passphrase can be given as parameter, using a
@@ -361,11 +363,10 @@ class Context(GpgmeWrapper):
         Returns:
         plaintext      -- the decrypted data (or None if sink is given)
         result         -- additional information about the decryption
-        verify_result  -- additional information about the signature(s)
+        verify_result  -- additional information about the valid signature(s) found
 
         Raises:
         UnsupportedAlgorithm -- if an unsupported algorithm was used
-        BadSignatures  -- if a bad signature is encountered
         MissingSignatures -- if expected signatures are missing or bad
         GPGMEError     -- as signaled by the underlying library
 
@@ -430,13 +431,8 @@ class Context(GpgmeWrapper):
                                               results=results)
 
         if do_sig_verification:
-            # FIXME: should we really throw BadSignature, even if
-            # we've encountered some good signatures?  as above, once
-            # we hit this error, there is no way to accept it and
-            # continue to process the remaining signatures.
-            if any(s.status != errors.NO_ERROR
-                   for s in verify_result.signatures):
-                raise errors.BadSignatures(verify_result, results=results)
+            # filter out all invalid signatures
+            verify_result.signatures = list(filter(lambda s: s.status == errors.NO_ERROR, verify_result.signatures))
             if required_keys is not None:
                 missing = []
                 for key in required_keys:
index 6a4fc55..300fc71 100755 (executable)
@@ -84,5 +84,6 @@ with gpg.Context() as c:
 
     plaintext, _, verify_result = c.decrypt(open(support.make_filename("cipher-3.asc")))
     assert len(plaintext) > 0
+    assert len(verify_result.signatures) == 1
     assert plaintext.find(b'Reenact Studied Thermos Bonehead Unclasp Opposing') >= 0, \
         'second Plaintext not found'