Skip to content

Commit

Permalink
Collect problems reported during verification.
Browse files Browse the repository at this point in the history
  • Loading branch information
vsajip committed Dec 2, 2022
1 parent f7023c6 commit 6081e55
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
8 changes: 8 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,8 @@ data that was signed should be in a separate file whose path is indicated by

* ``trust_text`` - the text corresponding to the trust level.

Note that only information for valid signatures will be present in ``sig_info``.

When a signature is verified, signer information is held in attributes of
``verified``: ``username``, ``key_id``, ``signature_id``, ``fingerprint``,
``trust_level`` and ``trust_text``. If the message wasn't signed, these attributes
Expand Down Expand Up @@ -1216,6 +1218,12 @@ key, the ``key_status`` attribute will be ``None``.
an existing file as well as text or a file-like object. In the pathname
case, ``python-gnupg`` will open and close the file for you.

.. versionadded:: 0.5.1
A ``problems`` attribute was added which holds problems reported by ``gpg``
during verification. This is a list of dictionaries, one for each reported
problem. Each dictionary will have ``status`` and ``keyid`` keys indicating
the problem and the corresponding key; other information in the dictionaries
will be error specific.


Verifying detached signatures in memory
Expand Down
29 changes: 29 additions & 0 deletions gnupg.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ def __init__(self, gpg):
self.trust_text = None
self.trust_level = None
self.sig_info = {}
self.problems = []

def __nonzero__(self): # pragma: no cover
return self.valid
Expand Down Expand Up @@ -316,6 +317,11 @@ def update_sig_info(**kwargs):
self.valid = False
self.status = 'signature bad'
self.key_id, self.username = value.split(None, 1)
self.problems.append({
'status': self.status,
'keyid': self.key_id,
'user': self.username
})
update_sig_info(keyid=self.key_id, username=self.username, status=self.status)
elif key == 'ERRSIG': # pragma: no cover
self.valid = False
Expand All @@ -329,11 +335,22 @@ def update_sig_info(**kwargs):
timestamp=self.timestamp,
fingerprint=self.fingerprint,
status=self.status)
self.problems.append({
'status': self.status,
'keyid': self.key_id,
'timestamp': self.timestamp,
'fingerprint': self.fingerprint
})
elif key == 'EXPSIG': # pragma: no cover
self.valid = False
self.status = 'signature expired'
self.key_id, self.username = value.split(None, 1)
update_sig_info(keyid=self.key_id, username=self.username, status=self.status)
self.problems.append({
'status': self.status,
'keyid': self.key_id,
'user': self.username
})
elif key == 'GOODSIG':
self.valid = True
self.status = 'signature good'
Expand Down Expand Up @@ -362,10 +379,18 @@ def update_sig_info(**kwargs):
self.valid = False
self.key_id = value
self.status = 'no public key'
self.problems.append({
'status': self.status,
'keyid': self.key_id
})
elif key == 'NO_SECKEY': # pragma: no cover
self.valid = False
self.key_id = value
self.status = 'no secret key'
self.problems.append({
'status': self.status,
'keyid': self.key_id
})
elif key in ('EXPKEYSIG', 'REVKEYSIG'): # pragma: no cover
# signed with expired or revoked key
self.valid = False
Expand All @@ -376,6 +401,10 @@ def update_sig_info(**kwargs):
self.key_status = 'signing key was revoked'
self.status = self.key_status
update_sig_info(status=self.status, keyid=self.key_id)
self.problems.append({
'status': self.status,
'keyid': self.key_id
})
elif key in ('UNEXPECTED', 'FAILURE'): # pragma: no cover
self.valid = False
if key == 'UNEXPECTED':
Expand Down
5 changes: 5 additions & 0 deletions test_gnupg.py
Original file line number Diff line number Diff line change
Expand Up @@ -1539,6 +1539,11 @@ def test_multiple_signatures_one_invalid(self):
actual = set(d['fingerprint'] for d in sig_info.values())
expected = set([key1.fingerprint])
self.assertEqual(actual, expected)
problems = verified.problems
self.assertEqual(len(problems), 1)
d = problems[0]
self.assertEqual(d['status'], 'signature bad')
self.assertTrue(key2.fingerprint.endswith(d['keyid']))
finally:
os.remove(fn)

Expand Down

0 comments on commit 6081e55

Please sign in to comment.