aboutsummaryrefslogtreecommitdiff
path: root/src/mailman_pgp/pgp/mime_multisig.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman_pgp/pgp/mime_multisig.py')
-rw-r--r--src/mailman_pgp/pgp/mime_multisig.py123
1 files changed, 66 insertions, 57 deletions
diff --git a/src/mailman_pgp/pgp/mime_multisig.py b/src/mailman_pgp/pgp/mime_multisig.py
index d7ad00a..1dbb73c 100644
--- a/src/mailman_pgp/pgp/mime_multisig.py
+++ b/src/mailman_pgp/pgp/mime_multisig.py
@@ -23,8 +23,8 @@ from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.utils import collapse_rfc2231_value
-from mailman.email.message import Message, MultipartDigestMessage
-from pgpy import PGPDetachedSignature, PGPSignature
+from mailman.email.message import Message
+from pgpy import PGPSignature
from mailman_pgp.pgp.mime import MIMEWrapper
from mailman_pgp.utils.email import copy_headers
@@ -74,30 +74,20 @@ class MIMEMultiSigWrapper(MIMEWrapper):
continue
yield sig
- def _wrap_signed_multiple(self, msg, payload_msg, sig_msgs, signatures,
- signature):
+ def sign(self, key, **kwargs):
"""
- As per draft-ietf-openpgp-multsig-02.
+ Sign a message with key.
- :param msg:
- :param payload_msg:
- :param sig_msgs:
- :param signatures:
- :param signature:
+ :param key: The key to sign with.
+ :type key: pgpy.PGPKey
:return:
+ :rtype: MIMEMultiSigWrapper
"""
- micalg = ', '.join(self._micalg(sig.hash_algorithm)
- for sig in signatures + signature.signatures)
- out = MultipartDigestMessage('signed', micalg=micalg,
- protocol='multipart/mixed')
- out.preamble = MIMEMultiSigWrapper._signature_preamble
- second_part = MIMEMultipart()
- for sig_msg in sig_msgs:
- second_part.attach(copy.deepcopy(sig_msg))
-
- for sig in signature.signatures:
- sig_part = MIMEApplication(_data=str(sig),
+ if self.is_signed():
+ signed = next(iter(self.get_signed()))
+ signature = key.sign(signed, **kwargs)
+ sig_part = MIMEApplication(_data=str(signature),
_subtype=MIMEWrapper._signature_subtype,
_encoder=encode_7or8bit,
name='signature.asc')
@@ -105,36 +95,34 @@ class MIMEMultiSigWrapper(MIMEWrapper):
'OpenPGP digital signature')
sig_part.add_header('Content-Disposition', 'attachment',
filename='signature.asc')
- second_part.attach(sig_part)
-
- out.attach(copy.deepcopy(payload_msg))
- out.attach(second_part)
- copy_headers(msg, out)
- return out
-
- def sign(self, key, **kwargs):
- """
- Sign a message with key.
-
- :param key: The key to sign with.
- :type key: pgpy.PGPKey
- :return: The signed message.
- :rtype: mailman.email.message.Message
- """
-
- if self.is_signed():
- payload_msg = self.msg.get_payload(0)
- sig_msgs = [part for part in self.msg.get_payload(1).get_payload()]
+ micalg = self.msg.get_param('micalg')
+ micalg += ',' + self._micalg(signature.hash_algorithm)
+ self.msg.set_param('micalg', micalg)
+ self.msg.get_payload(1).attach(sig_part)
else:
- payload_msg = self.msg
- sig_msgs = []
- # TODO: exception safe this
- signatures = [PGPSignature.from_blob(sig_msg.get_payload())
- for sig_msg in sig_msgs]
- signature = PGPDetachedSignature()
- signature |= key.sign(payload_msg.as_string(), **kwargs)
- return self._wrap_signed_multiple(self.msg, payload_msg, sig_msgs,
- signatures, signature)
+ original_msg = copy.deepcopy(self.msg)
+ to_sign = next(iter(self.get_payload()))
+ signature = key.sign(to_sign, **kwargs)
+ self.msg.set_payload([])
+ self.msg.attach(original_msg)
+ self.msg.set_type('multipart/signed')
+ self.msg['MIME-Version'] = '1.0'
+ self.msg.set_param('protocol', 'multipart/mixed')
+ self.msg.set_param('micalg',
+ self._micalg(signature.hash_algorithm))
+ sig_part = MIMEApplication(_data=str(signature),
+ _subtype=MIMEWrapper._signature_subtype,
+ _encoder=encode_7or8bit,
+ name='signature.asc')
+ sig_part.add_header('Content-Description',
+ 'OpenPGP digital signature')
+ sig_part.add_header('Content-Disposition', 'attachment',
+ filename='signature.asc')
+ second_part = MIMEMultipart()
+ second_part.attach(sig_part)
+ self.msg.attach(second_part)
+ self.msg.preamble = MIMEMultiSigWrapper._signature_preamble
+ return self
def verify(self, key):
"""
@@ -159,11 +147,10 @@ class MIMEMultiSigWrapper(MIMEWrapper):
:param key: The key to decrypt with.
:type key: pgpy.PGPKey
- :return: The decrypted message.
- :rtype: mailman.email.message.Message
+ :return:
+ :rtype: MIMEMultiSigWrapper
"""
pmsg = next(iter(self.get_encrypted()))
- # TODO: exception safe this
decrypted = key.decrypt(pmsg)
dmsg = decrypted.message
@@ -172,8 +159,30 @@ class MIMEMultiSigWrapper(MIMEWrapper):
out = message_from_string(dmsg, _class=Message)
if decrypted.is_signed:
- out = self._wrap_signed_multiple(self.msg, out, [], [],
- decrypted.detached_signature)
+ # result should be a multisig signed thing, so [out, ]
+ self.msg.set_payload([])
+ self.msg.attach(out)
+ self.msg.set_type('multipart/signed')
+ self.msg['MIME-Version'] = '1.0'
+ self.msg.set_param('protocol', 'multipart/mixed')
+ micalg = ', '.join(self._micalg(sig.hash_algorithm)
+ for sig in decrypted.signatures)
+ self.msg.set_param('micalg', micalg)
+ second_part = MIMEMultipart()
+ for signature in decrypted.signatures:
+ sig_part = MIMEApplication(_data=str(signature),
+ _subtype=MIMEWrapper._signature_subtype,
+ _encoder=encode_7or8bit,
+ name='signature.asc')
+ sig_part.add_header('Content-Description',
+ 'OpenPGP digital signature')
+ sig_part.add_header('Content-Disposition', 'attachment',
+ filename='signature.asc')
+ second_part.attach(sig_part)
+ self.msg.attach(second_part)
else:
- copy_headers(self.msg, out)
- return out
+ # result should be
+ self.msg.set_payload(out.get_payload())
+ copy_headers(out, self.msg, True)
+
+ return self