diff options
Diffstat (limited to 'src/mailman_pgp/pgp/mime_multisig.py')
| -rw-r--r-- | src/mailman_pgp/pgp/mime_multisig.py | 68 |
1 files changed, 37 insertions, 31 deletions
diff --git a/src/mailman_pgp/pgp/mime_multisig.py b/src/mailman_pgp/pgp/mime_multisig.py index ced90fa..c7edf60 100644 --- a/src/mailman_pgp/pgp/mime_multisig.py +++ b/src/mailman_pgp/pgp/mime_multisig.py @@ -15,7 +15,7 @@ # You should have received a copy of the GNU General Public License along with # this program. If not, see <http://www.gnu.org/licenses/>. -"""""" +"""MIMEWrapper with multiple signature as per draft-ietf-openpgp-multsig-02.""" import copy from email import message_from_string from email.encoders import encode_7or8bit @@ -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 MultipartDigestMessage, Message -from pgpy import PGPSignature, PGPDetachedSignature +from mailman.email.message import Message, MultipartDigestMessage +from pgpy import PGPDetachedSignature, PGPSignature from mailman_pgp.pgp.mime import MIMEWrapper from mailman_pgp.utils.email import copy_headers @@ -41,7 +41,7 @@ class MIMEMultiSigWrapper(MIMEWrapper): def is_signed(self): """ - Whether the whole message is MIME signed as per draft-ietf-openpgp-multsig-02. + Whether the message is signed as per draft-ietf-openpgp-multsig-02. :return: If the message is MIME signed. :rtype: bool @@ -74,32 +74,36 @@ class MIMEMultiSigWrapper(MIMEWrapper): continue yield sig - def _wrap_signed_multiple(self, msg, signature): + def _wrap_signed_multiple(self, msg, payload_msg, signatures, signature): """ As per draft-ietf-openpgp-multsig-02. :param msg: + :param payload_msg: + :param signatures: :param signature: :return: """ micalg = ', '.join(self._micalg(sig.hash_algorithm) for sig in signature) out = MultipartDigestMessage('signed', micalg=micalg, - protocol=MIMEWrapper._signed_type) + protocol='multipart/mixed') out.preamble = MIMEMultiSigWrapper._signature_preamble second_part = MIMEMultipart() - for sig in signature: - sig_part = MIMEApplication(_data=str(sig), - _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) - out.attach(copy.deepcopy(msg)) + for sig in signatures: + second_part.attach(copy.deepcopy(sig)) + + 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) + out.attach(copy.deepcopy(payload_msg)) out.attach(second_part) copy_headers(msg, out) return out @@ -115,19 +119,21 @@ class MIMEMultiSigWrapper(MIMEWrapper): :return: The signed message. :rtype: mailman.email.message.Message """ + if self.is_signed(): - payload = next(iter(self.get_signed())) - signature = PGPDetachedSignature() - for sig in self.get_signature(): - signature |= sig - signature |= key.sign(payload, hash=hash) - return self._wrap_signed_multiple(self.msg, signature) + payload_msg = self.msg.get_payload(0) + signatures = [part for part in self.msg.get_payload(1)] else: - super().sign(key, hash) + payload_msg = self.msg + signatures = [] + signature = PGPDetachedSignature() + signature |= key.sign(payload_msg.as_string(), hash=hash) + return self._wrap_signed_multiple(self.msg, payload_msg, signatures, + signature) def verify(self, key): """ - Verify the signature of this message with key. + Verify the signatures of this message with key. :param key: The key to verify with. :type key: pgpy.PGPKey @@ -136,7 +142,11 @@ class MIMEMultiSigWrapper(MIMEWrapper): """ clear_text = next(iter(self.get_signed())) for signature in self.get_signature(): - yield key.verify(clear_text, signature) + try: + verification = key.verify(clear_text, signature) + except: + continue + yield verification def decrypt(self, key): """ @@ -156,10 +166,6 @@ class MIMEMultiSigWrapper(MIMEWrapper): out = message_from_string(dmsg, _class=Message) if decrypted.is_signed: - if len(decrypted.signatures) != 1: - out = self._wrap_signed_multiple(out, - decrypted.detached_signature) - else: - out = self._wrap_signed(out, decrypted.signatures.pop()) + out = self._wrap_signed_multiple(out, decrypted.detached_signature) copy_headers(self.msg, out) return out |
