diff options
Diffstat (limited to 'src/mailman_pgp/pgp')
| -rw-r--r-- | src/mailman_pgp/pgp/inline.py | 53 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/mime.py | 89 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/data/messages/inline_revoc.eml | 19 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/data/messages/inline_revoc_multipart.eml | 30 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/data/messages/mime_revoc.eml | 35 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/data/revocs/dsa_elgamal_1024.revoc.asc | 8 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/data/revocs/ecc_curve25519.revoc.asc | 8 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/data/revocs/ecc_p256.revoc.asc | 8 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/data/revocs/ecc_secp256k1.revoc.asc | 8 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/data/revocs/rsa_1024.revoc.asc | 9 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/test_inline.py | 43 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/test_mime.py | 48 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/test_wrapper.py | 38 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/wrapper.py | 31 |
14 files changed, 402 insertions, 25 deletions
diff --git a/src/mailman_pgp/pgp/inline.py b/src/mailman_pgp/pgp/inline.py index bb0971d..49f0a6e 100644 --- a/src/mailman_pgp/pgp/inline.py +++ b/src/mailman_pgp/pgp/inline.py @@ -18,12 +18,14 @@ """Strict inline PGP message wrapper.""" import copy from email.iterators import walk +from email.mime.text import MIMEText from pgpy import PGPMessage from pgpy.constants import SymmetricKeyAlgorithm from public import public -from mailman_pgp.utils.pgp import key_from_blob +from mailman_pgp.utils.email import make_multipart +from mailman_pgp.utils.pgp import key_from_blob, revoc_from_blob @public @@ -95,7 +97,7 @@ class InlineWrapper: :rtype: typing.Generator[pgpy.PGPMessage] """ for part in walk(self.msg): - if not part.is_multipart() and self._is_signed(part): + if not part.is_multipart(): try: msg = PGPMessage.from_blob(part.get_payload()) except: @@ -135,7 +137,7 @@ class InlineWrapper: :rtype: typing.Generator[pgpy.PGPMessage] """ for part in walk(self.msg): - if not part.is_multipart() and self._is_encrypted(part): + if not part.is_multipart(): try: msg = PGPMessage.from_blob(part.get_payload()) except: @@ -176,13 +178,56 @@ class InlineWrapper: :rtype: Generator[pgpy.PGPKey] """ for part in walk(self.msg): - if not part.is_multipart() and self._has_keys(part): + if not part.is_multipart(): try: key = key_from_blob(part.get_payload()) except: continue yield key + def _is_revoc(self, part): + try: + revoc_from_blob(part.get_payload()) + except ValueError: + return False + return True + + def is_revocs(self): + for part in walk(self.msg): + if (not part.is_multipart() and not self._is_revoc(part)): + return False + return True + + def has_revocs(self): + for part in walk(self.msg): + if (not part.is_multipart() and self._is_revoc(part)): + return True + return False + + def revocs(self): + for part in walk(self.msg): + if not part.is_multipart(): + try: + revoc = revoc_from_blob(part.get_payload()) + except: + continue + yield revoc + + def attach_revocs(self, *key_revocations): + """ + Attach a key revocation signature to the message. + + :param key_revocations: A key revocation signature to attach. + :type key_revocations: pgpy.PGPSignature + :return: The message with the signature attached. + :rtype: mailman.email.message.Message + """ + out = make_multipart(self.msg) + for key_revocation in key_revocations: + revoc_part = MIMEText(str(key_revocation)) + out.attach(revoc_part) + return out + def verify(self, key): """ Verify the signatures of this message with key. diff --git a/src/mailman_pgp/pgp/mime.py b/src/mailman_pgp/pgp/mime.py index a1303c9..03177ab 100644 --- a/src/mailman_pgp/pgp/mime.py +++ b/src/mailman_pgp/pgp/mime.py @@ -28,8 +28,8 @@ from pgpy import PGPDetachedSignature, PGPMessage from pgpy.constants import HashAlgorithm, SymmetricKeyAlgorithm from public import public -from mailman_pgp.utils.email import copy_headers -from mailman_pgp.utils.pgp import key_from_blob +from mailman_pgp.utils.email import copy_headers, make_multipart +from mailman_pgp.utils.pgp import key_from_blob, revoc_from_blob @public @@ -63,7 +63,7 @@ class MIMEWrapper: def _is_mime(self): is_multipart = self.msg.is_multipart() - payloads = len(self.msg.get_payload()) + payloads = len(self.msg.get_payload()) if self.msg.get_payload() else 0 return is_multipart and payloads == 2 @@ -186,26 +186,81 @@ class MIMEWrapper: continue yield key - def attach_key(self, key): + def attach_keys(self, *keys): """ Attach a key to this message, as per RFC3156 section 7. - :param key: A key to attach. - :type key: pgpy.PGPKey + :param keys: A key to attach. + :type keys: pgpy.PGPKey :return: The message with the key attached. :rtype: mailman.email.message.Message """ - filename = '0x' + key.fingerprint.keyid + '.asc' - key_part = MIMEApplication(_data=str(key), - _subtype=MIMEWrapper._keys_subtype, - _encoder=encode_7or8bit, - name=filename) - key_part.add_header('Content-Description', - 'OpenPGP key') - key_part.add_header('Content-Disposition', 'attachment', - filename=filename) - out = copy.deepcopy(self.msg) - out.attach(key_part) + out = make_multipart(self.msg) + for key in keys: + filename = '0x' + key.fingerprint.keyid + '.asc' + key_part = MIMEApplication(_data=str(key), + _subtype=MIMEWrapper._keys_subtype, + _encoder=encode_7or8bit, + name=filename) + key_part.add_header('Content-Description', + 'OpenPGP key') + key_part.add_header('Content-Disposition', 'attachment', + filename=filename) + out.attach(key_part) + return out + + def _is_revoc(self, part): + if part.get_content_type() != MIMEWrapper._keys_type: + return False + try: + revoc_from_blob(part.get_payload()) + except ValueError: + return False + return True + + def is_revocs(self): + for part in walk(self.msg): + if (not part.is_multipart() and not self._is_revoc(part)): + return False + return True + + def has_revocs(self): + for part in walk(self.msg): + if (not part.is_multipart() and self._is_revoc(part)): + return True + return False + + def revocs(self): + for part in walk(self.msg): + if (not part.is_multipart() # noqa + and part.get_content_type() == MIMEWrapper._keys_type): + try: + revoc = revoc_from_blob(part.get_payload()) + except: + continue + yield revoc + + def attach_revocs(self, *key_revocations): + """ + Attach a key revocation signature to the message, as a key subpart. + + :param key_revocations: A key revocation signature to attach. + :type key_revocations: pgpy.PGPSignature + :return: The message with the signature attached. + :rtype: mailman.email.message.Message + """ + out = make_multipart(self.msg) + for key_revocation in key_revocations: + filename = '0x' + key_revocation.signer + '.asc' + revoc_part = MIMEApplication(_data=str(key_revocation), + _subtype=MIMEWrapper._keys_subtype, + _encoder=encode_7or8bit, + name=filename) + revoc_part.add_header('Content-Description', + 'OpenPGP key') + revoc_part.add_header('Content-Disposition', 'attachment', + filename=filename) + out.attach(revoc_part) return out def verify(self, key): diff --git a/src/mailman_pgp/pgp/tests/data/messages/inline_revoc.eml b/src/mailman_pgp/pgp/tests/data/messages/inline_revoc.eml new file mode 100644 index 0000000..f215777 --- /dev/null +++ b/src/mailman_pgp/pgp/tests/data/messages/inline_revoc.eml @@ -0,0 +1,19 @@ +To: nobody@example.org +From: RSA 1024b example <RSA-1024b@example.org> +Subject: Some subject. +Message-ID: <76a591ed-bfc4-d08b-73d3-fc2489148fd7@example.org> +Date: Wed, 21 Jun 2017 13:50:59 +0200 +User-Agent: Mutt/1.7.2 (2016-11-26) +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 8bit + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: This is a revocation certificate + +iLYEIAEIACAWIQTUqUiGscoglqZFjlxH8QwIeIS3WAUCWYClvgIdAgAKCRBH8QwI +eIS3WLpBBADCUtyYmI2Z8DCOnKUW4nRjHc3ZVMoZJlwceJCWhSybBrnjo6LWzvBy +eKke4qHlh+jmSk3/Qyio6vYzvicOayDwhr0s/1X26MiYorthfiCQOg2WQ0YiRuMC +/Ml8rukvBTRGvXikcIuBw5MFqCWsWI7ExPKaaresnHaCn37KF0A6hw== +=4oku +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/mailman_pgp/pgp/tests/data/messages/inline_revoc_multipart.eml b/src/mailman_pgp/pgp/tests/data/messages/inline_revoc_multipart.eml new file mode 100644 index 0000000..a1052d6 --- /dev/null +++ b/src/mailman_pgp/pgp/tests/data/messages/inline_revoc_multipart.eml @@ -0,0 +1,30 @@ +To: nobody@example.org +From: RSA 1024b example <RSA-1024b@example.org> +Subject: Some subject. +Message-ID: <76a591ed-bfc4-d08b-73d3-fc2489148fd7@example.org> +Date: Wed, 21 Jun 2017 13:50:59 +0200 +User-Agent: Mutt/1.7.2 (2016-11-26) +MIME-Version: 1.0 +Content-Type: multipart/mixed; boundary="abjqkjsfwqsfa546qw2wfq6sdq2sqwr56qqs" + +--abjqkjsfwqsfa546qw2wfq6sdq2sqwr56qqs +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 8bit + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: This is a revocation certificate + +iLYEIAEIACAWIQTUqUiGscoglqZFjlxH8QwIeIS3WAUCWYClvgIdAgAKCRBH8QwI +eIS3WLpBBADCUtyYmI2Z8DCOnKUW4nRjHc3ZVMoZJlwceJCWhSybBrnjo6LWzvBy +eKke4qHlh+jmSk3/Qyio6vYzvicOayDwhr0s/1X26MiYorthfiCQOg2WQ0YiRuMC +/Ml8rukvBTRGvXikcIuBw5MFqCWsWI7ExPKaaresnHaCn37KF0A6hw== +=4oku +-----END PGP PUBLIC KEY BLOCK----- + +--abjqkjsfwqsfa546qw2wfq6sdq2sqwr56qqs +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 8bit + +Some cleartext. + +--abjqkjsfwqsfa546qw2wfq6sdq2sqwr56qqs--
\ No newline at end of file diff --git a/src/mailman_pgp/pgp/tests/data/messages/mime_revoc.eml b/src/mailman_pgp/pgp/tests/data/messages/mime_revoc.eml new file mode 100644 index 0000000..e1055a3 --- /dev/null +++ b/src/mailman_pgp/pgp/tests/data/messages/mime_revoc.eml @@ -0,0 +1,35 @@ +To: nobody@example.org +From: RSA 1024b example <RSA-1024b@example.org> +Subject: Some subject. +Message-ID: <76a591ed-bfc4-d08b-73d3-fc2489148fd7@example.org> +Date: Wed, 21 Jun 2017 13:50:59 +0200 +User-Agent: Mutt/1.7.2 (2016-11-26) +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="------------A851F166D50529639139DD0B" + +This is a multi-part message in MIME format. +--------------A851F166D50529639139DD0B +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 7bit + +Some other text. + +--------------A851F166D50529639139DD0B +Content-Type: application/pgp-keys; + name="0x7884B758.asc" +Content-Transfer-Encoding: 7bit +Content-Disposition: attachment; + filename="0x7884B758.asc" + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: This is a revocation certificate + +iLYEIAEIACAWIQTUqUiGscoglqZFjlxH8QwIeIS3WAUCWYClvgIdAgAKCRBH8QwI +eIS3WLpBBADCUtyYmI2Z8DCOnKUW4nRjHc3ZVMoZJlwceJCWhSybBrnjo6LWzvBy +eKke4qHlh+jmSk3/Qyio6vYzvicOayDwhr0s/1X26MiYorthfiCQOg2WQ0YiRuMC +/Ml8rukvBTRGvXikcIuBw5MFqCWsWI7ExPKaaresnHaCn37KF0A6hw== +=4oku +-----END PGP PUBLIC KEY BLOCK----- + +--------------A851F166D50529639139DD0B-- diff --git a/src/mailman_pgp/pgp/tests/data/revocs/dsa_elgamal_1024.revoc.asc b/src/mailman_pgp/pgp/tests/data/revocs/dsa_elgamal_1024.revoc.asc new file mode 100644 index 0000000..80b002e --- /dev/null +++ b/src/mailman_pgp/pgp/tests/data/revocs/dsa_elgamal_1024.revoc.asc @@ -0,0 +1,8 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: This is a revocation certificate + +iGAEIBECACAWIQRR5fGEErwNQ8nevZPDzAoGOEHHpwUCWYCmxwIdAgAKCRDDzAoG +OEHHp+nYAJwM095Qv9qxaMfqx8xSLD5eKeExgQCeNA5z7zZZcgtUTTqW/o4baX6D +X8E= +=vVlH +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/mailman_pgp/pgp/tests/data/revocs/ecc_curve25519.revoc.asc b/src/mailman_pgp/pgp/tests/data/revocs/ecc_curve25519.revoc.asc new file mode 100644 index 0000000..df7d593 --- /dev/null +++ b/src/mailman_pgp/pgp/tests/data/revocs/ecc_curve25519.revoc.asc @@ -0,0 +1,8 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: This is a revocation certificate + +iHgEIBYIACAWIQQFsA605escSIQh4V/6me+juNPIugUCWYCmggIdAgAKCRD6me+j +uNPIuuVxAP4mr8PXnLIzqdysvMo5Mo0QbIck6NgO/rOJC4Kj/tGjyQD/QMo4ON/1 +cxzD068xWtlDpPYjtPBFuNYrLOPDYvqjGAg= +=0TTd +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/mailman_pgp/pgp/tests/data/revocs/ecc_p256.revoc.asc b/src/mailman_pgp/pgp/tests/data/revocs/ecc_p256.revoc.asc new file mode 100644 index 0000000..9571cd2 --- /dev/null +++ b/src/mailman_pgp/pgp/tests/data/revocs/ecc_p256.revoc.asc @@ -0,0 +1,8 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: This is a revocation certificate + +iHgEIBMIACAWIQSyKLDm+5ZVhlrf0j03k3IFvhWo0AUCWYCmZAIdAgAKCRA3k3IF +vhWo0HAZAP9qFHrB6d+hNpYDT9jVCDIURh8Ml711hi8zsDhSkRZ4yAEAgzlmzjPZ +VhgcOemgbYTKO7Kj8q61KpVP9oZ9l7Z4c/I= +=ZZsy +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/mailman_pgp/pgp/tests/data/revocs/ecc_secp256k1.revoc.asc b/src/mailman_pgp/pgp/tests/data/revocs/ecc_secp256k1.revoc.asc new file mode 100644 index 0000000..e91a62a --- /dev/null +++ b/src/mailman_pgp/pgp/tests/data/revocs/ecc_secp256k1.revoc.asc @@ -0,0 +1,8 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: This is a revocation certificate + +iHgEIBMIACAWIQRi7dSuUMnX5cDo6nvIw1p/AFOkvwUCWYCmEwIdAgAKCRDIw1p/ +AFOkv5zZAQDiOzuQWpL2cvm+Jz4XyeLWebiOe7zirM9oMP03rmzQxgD/UIzBnqq9 +iy6oREDvbNw1sCB8/90ihlkB3iM8eOW9iSk= +=lj1I +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/mailman_pgp/pgp/tests/data/revocs/rsa_1024.revoc.asc b/src/mailman_pgp/pgp/tests/data/revocs/rsa_1024.revoc.asc new file mode 100644 index 0000000..ddb8974 --- /dev/null +++ b/src/mailman_pgp/pgp/tests/data/revocs/rsa_1024.revoc.asc @@ -0,0 +1,9 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: This is a revocation certificate + +iLYEIAEIACAWIQTUqUiGscoglqZFjlxH8QwIeIS3WAUCWYClvgIdAgAKCRBH8QwI +eIS3WLpBBADCUtyYmI2Z8DCOnKUW4nRjHc3ZVMoZJlwceJCWhSybBrnjo6LWzvBy +eKke4qHlh+jmSk3/Qyio6vYzvicOayDwhr0s/1X26MiYorthfiCQOg2WQ0YiRuMC +/Ml8rukvBTRGvXikcIuBw5MFqCWsWI7ExPKaaresnHaCn37KF0A6hw== +=4oku +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/mailman_pgp/pgp/tests/test_inline.py b/src/mailman_pgp/pgp/tests/test_inline.py index 7f82ab4..d9f8c8a 100644 --- a/src/mailman_pgp/pgp/tests/test_inline.py +++ b/src/mailman_pgp/pgp/tests/test_inline.py @@ -20,7 +20,8 @@ from parameterized import parameterized from mailman_pgp.pgp.inline import InlineWrapper -from mailman_pgp.testing.pgp import load_key, load_message, WrapperTestCase +from mailman_pgp.testing.pgp import ( + load_key, load_message, load_revoc, WrapperTestCase) class InlineWrapperTestCase(WrapperTestCase): @@ -219,6 +220,46 @@ class TestKeys(InlineWrapperTestCase): self.keys(message, keys) +class TestRevocs(InlineWrapperTestCase): + @parameterized.expand([ + (load_message('inline_revoc.eml'), + True), + (load_message('inline_revoc_multipart.eml'), + True) + ]) + def test_has_revocs(self, message, has_revocs): + self.has_revocs(message, has_revocs) + + @parameterized.expand([ + (load_message('inline_revoc.eml'), + True), + (load_message('inline_revoc_multipart.eml'), + False) + ]) + def test_is_revocs(self, message, is_revocs): + self.is_revocs(message, is_revocs) + + @parameterized.expand([ + (load_message('inline_revoc.eml'), + (load_revoc('rsa_1024.revoc.asc'),)), + (load_message('inline_revoc_multipart.eml'), + (load_revoc('rsa_1024.revoc.asc'),)) + ]) + def test_revocs(self, message, revocs): + self.revocs(message, revocs) + + @parameterized.expand([ + (load_message('clear.eml'), + [load_revoc('rsa_1024.revoc.asc'), + load_revoc('ecc_p256.revoc.asc')]), + (load_message('clear_multipart.eml'), + [load_revoc('rsa_1024.revoc.asc'), + load_revoc('ecc_p256.revoc.asc')]) + ]) + def test_attach_revocs(self, message, revocs): + self.attach_revocs(message, revocs) + + class TestCombined(InlineWrapperTestCase): @parameterized.expand([ (load_message('clear.eml'), diff --git a/src/mailman_pgp/pgp/tests/test_mime.py b/src/mailman_pgp/pgp/tests/test_mime.py index 78c9e71..e9951cf 100644 --- a/src/mailman_pgp/pgp/tests/test_mime.py +++ b/src/mailman_pgp/pgp/tests/test_mime.py @@ -20,7 +20,8 @@ from parameterized import parameterized from mailman_pgp.pgp.mime import MIMEWrapper -from mailman_pgp.testing.pgp import load_key, load_message, WrapperTestCase +from mailman_pgp.testing.pgp import ( + load_key, load_message, load_revoc, WrapperTestCase) class MIMEWrapperTestCase(WrapperTestCase): @@ -178,6 +179,51 @@ class TestKeys(MIMEWrapperTestCase): def test_keys(self, message, keys): self.keys(message, keys) + @parameterized.expand([ + (load_message('clear.eml'), + [load_key('rsa_1024.priv.asc'), + load_key('ecc_p256.priv.asc')]), + (load_message('clear_multipart.eml'), + [load_key('rsa_1024.priv.asc'), + load_key('ecc_p256.priv.asc')]) + ]) + def test_attach_keys(self, message, keys): + self.attach_keys(message, keys) + + +class TestRevocs(MIMEWrapperTestCase): + @parameterized.expand([ + (load_message('mime_revoc.eml'), + True) + ]) + def test_has_revocs(self, message, has_revocs): + self.has_revocs(message, has_revocs) + + @parameterized.expand([ + (load_message('mime_revoc.eml'), + False) + ]) + def test_is_revocs(self, message, is_revocs): + self.is_revocs(message, is_revocs) + + @parameterized.expand([ + (load_message('mime_revoc.eml'), + (load_revoc('rsa_1024.revoc.asc'),)) + ]) + def test_revocs(self, message, revocs): + self.revocs(message, revocs) + + @parameterized.expand([ + (load_message('clear.eml'), + [load_revoc('rsa_1024.revoc.asc'), + load_revoc('ecc_p256.revoc.asc')]), + (load_message('clear_multipart.eml'), + [load_revoc('rsa_1024.revoc.asc'), + load_revoc('ecc_p256.revoc.asc')]) + ]) + def test_attach_revocs(self, message, revocs): + self.attach_revocs(message, revocs) + class TestCombined(MIMEWrapperTestCase): @parameterized.expand([ diff --git a/src/mailman_pgp/pgp/tests/test_wrapper.py b/src/mailman_pgp/pgp/tests/test_wrapper.py index f1f7621..b9c157a 100644 --- a/src/mailman_pgp/pgp/tests/test_wrapper.py +++ b/src/mailman_pgp/pgp/tests/test_wrapper.py @@ -22,7 +22,8 @@ from mailman_pgp.pgp.inline import InlineWrapper from mailman_pgp.pgp.mime import MIMEWrapper from mailman_pgp.pgp.mime_multisig import MIMEMultiSigWrapper from mailman_pgp.pgp.wrapper import PGPWrapper -from mailman_pgp.testing.pgp import load_key, load_message, WrapperTestCase +from mailman_pgp.testing.pgp import ( + load_key, load_message, load_revoc, WrapperTestCase) class PGPWrapperTestCase(WrapperTestCase): @@ -180,6 +181,41 @@ class TestKeys(PGPWrapperTestCase): self.keys(message, keys) +class TestRevocs(PGPWrapperTestCase): + @parameterized.expand([ + (load_message('mime_revoc.eml'), + True), + (load_message('inline_revoc.eml'), + True), + (load_message('inline_revoc_multipart.eml'), + True) + ]) + def test_has_revocs(self, message, has_revocs): + self.has_revocs(message, has_revocs) + + @parameterized.expand([ + (load_message('mime_revoc.eml'), + False), + (load_message('inline_revoc.eml'), + True), + (load_message('inline_revoc_multipart.eml'), + False) + ]) + def test_is_revocs(self, message, is_revocs): + self.is_revocs(message, is_revocs) + + @parameterized.expand([ + (load_message('mime_revoc.eml'), + (load_revoc('rsa_1024.revoc.asc'),)), + (load_message('inline_revoc.eml'), + (load_revoc('rsa_1024.revoc.asc'),)), + (load_message('inline_revoc_multipart.eml'), + (load_revoc('rsa_1024.revoc.asc'),)) + ]) + def test_revocs(self, message, revocs): + self.revocs(message, revocs) + + class TestCombined(PGPWrapperTestCase): @parameterized.expand([ (load_message('clear.eml'), diff --git a/src/mailman_pgp/pgp/wrapper.py b/src/mailman_pgp/pgp/wrapper.py index 6193b57..f0519cb 100644 --- a/src/mailman_pgp/pgp/wrapper.py +++ b/src/mailman_pgp/pgp/wrapper.py @@ -270,7 +270,7 @@ class PGPWrapper(): Get the collection of keys in this message. :return: A collection of keys. - :rtype: Generator[pgpy.PGPKey] + :rtype: typing.Generator[pgpy.PGPKey] """ if self.mime.has_keys(): yield from self.mime.keys() @@ -278,3 +278,32 @@ class PGPWrapper(): yield from self.multisig.keys() elif self.inline.has_keys(): yield from self.inline.keys() + + def has_revocs(self): + """ + + :return: + :rtype: bool + """ + return any(wrapper.has_revocs() for wrapper in self.wrappers) + + def is_revocs(self): + """ + + :return: + :rtype: bool + """ + return any(wrapper.is_revocs() for wrapper in self.wrappers) + + def revocs(self): + """ + + :return: + :rtype: typing.Generator[pgpy.PGPSignature] + """ + if self.mime.has_revocs(): + yield from self.mime.revocs() + elif self.multisig.has_revocs(): + yield from self.multisig.revocs() + elif self.inline.has_revocs(): + yield from self.inline.revocs() |
