diff options
Diffstat (limited to 'src/mailman_pgp/pgp')
| -rw-r--r-- | src/mailman_pgp/pgp/inline.py | 17 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/mime.py | 60 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/test_inline.py | 11 | ||||
| -rw-r--r-- | src/mailman_pgp/pgp/tests/test_mime.py | 22 |
4 files changed, 81 insertions, 29 deletions
diff --git a/src/mailman_pgp/pgp/inline.py b/src/mailman_pgp/pgp/inline.py index cf92ffc..49f0a6e 100644 --- a/src/mailman_pgp/pgp/inline.py +++ b/src/mailman_pgp/pgp/inline.py @@ -18,11 +18,13 @@ """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.email import make_multipart from mailman_pgp.utils.pgp import key_from_blob, revoc_from_blob @@ -211,6 +213,21 @@ class InlineWrapper: 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 e40f581..837e619 100644 --- a/src/mailman_pgp/pgp/mime.py +++ b/src/mailman_pgp/pgp/mime.py @@ -28,7 +28,7 @@ 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.email import copy_headers, make_multipart from mailman_pgp.utils.pgp import key_from_blob, revoc_from_blob @@ -186,26 +186,27 @@ 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): @@ -239,26 +240,27 @@ class MIMEWrapper: continue yield revoc - def attach_revoc(self, key_revocation): + def attach_revocs(self, *key_revocations): """ Attach a key revocation signature to the message, as a key subpart. - :param key_revocation: A key revocation signature to attach. - :type key_revocation: pgpy.PGPSignature + :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 """ - filename = '0x' + key_revocation.signer + '.asc' - key_part = MIMEApplication(_data=str(key_revocation), - _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_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/test_inline.py b/src/mailman_pgp/pgp/tests/test_inline.py index b409bee..1f1f687 100644 --- a/src/mailman_pgp/pgp/tests/test_inline.py +++ b/src/mailman_pgp/pgp/tests/test_inline.py @@ -248,6 +248,17 @@ class TestRevocs(InlineWrapperTestCase): 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([ diff --git a/src/mailman_pgp/pgp/tests/test_mime.py b/src/mailman_pgp/pgp/tests/test_mime.py index ec2542a..f059c8d 100644 --- a/src/mailman_pgp/pgp/tests/test_mime.py +++ b/src/mailman_pgp/pgp/tests/test_mime.py @@ -179,6 +179,17 @@ 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([ @@ -202,6 +213,17 @@ class TestRevocs(MIMEWrapperTestCase): 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([ |
