Exaclty..
I'm able to get sign and body with this:
def get_signed_parts(message):
ct = message.get_content_type()
assert ct == 'multipart/signed', ct
params = dict(message.get_params())
assert params.get('protocol', None) == 'application/pgp-signature', params
assert message.is_multipart(), message
body = signature = None
for part in message.get_payload():
if part == message:
continue
ct = part.get_content_type()
if ct == 'application/pgp-signature':
if signature:
raise ValueError('multiple application/pgp-signature parts')
signature = part
else:
if body:
raise ValueError('multiple non-signature parts')
body = part
if not body:
raise ValueError('missing body part')
if not signature:
raise ValueError('missing application/pgp-signature part')
return (body, signature)
Then I try get a body flatten version with this:
def flatten(msg, to_unicode=False):
"""
Produce flat text output from an email Message instance.
"""
from email.generator import Generator
from cStringIO import StringIO
assert msg is not None
fp = StringIO()
g = Generator(fp, mangle_from_=False)
g.flatten(msg)
text = fp.getvalue()
if to_unicode is True:
encoding = msg.get_content_charset() or "utf-8"
text = unicode(text, encoding=encoding)
return text
Finally use python-gnupg in this way:
def verify(data):
from gnupg import GPG
from json import dumps as toJSON
import email
message = email.message_from_string(data)
if message.get_content_type() == 'multipart/mixed':
message = message.get_payload()[0]
if message.get_content_type() == 'multipart/signed':
body, signature = get_signed_parts(message)
open('/tmp/t.asc', 'w').write(signature.get_payload(decode=True))
verified = gpg.verify_data('/tmp/t.asc', flatten(body))
else:
verified = gpg.verified(data)
verified = verified.__dict__
del(verified['gpg'])
return toJSON(verified, indent=4)
It works properly with inline signature, but return "status": "signature bad" for email with sign attached.
Any tip?