aboutsummaryrefslogtreecommitdiff
path: root/src/mailman_pgp/pgp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman_pgp/pgp')
-rw-r--r--src/mailman_pgp/pgp/inline.py17
-rw-r--r--src/mailman_pgp/pgp/mime.py60
-rw-r--r--src/mailman_pgp/pgp/tests/test_inline.py11
-rw-r--r--src/mailman_pgp/pgp/tests/test_mime.py22
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([