openpgp.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. # coding: utf-8
  2. from __future__ import print_function
  3. from __future__ import absolute_import
  4. from __future__ import division
  5. from __future__ import unicode_literals
  6. import email
  7. import six
  8. import re
  9. class RFC3156(object):
  10. """
  11. Access data inside OpenPGP MIME emails
  12. """
  13. def __init__(self, data):
  14. self.data = data
  15. self.message = email.message_from_string(self.data)
  16. self.parsed = self.find_payloads(self.message)
  17. def find_payloads(self, message):
  18. # https://tools.ietf.org/html/rfc3156
  19. # RFC3156 extraction initially taken from http://domnit.org/scripts/clearmime
  20. # and from http://anonscm.debian.org/cgit/nm/nm.git/tree/bin/dm_verify_application?id=a188cfe89f530c68a2002bb61016cc041848e5f5
  21. if message.get_content_type() == 'multipart/signed':
  22. if message.get_param('protocol') == 'application/pgp-signature':
  23. hashname = message.get_param('micalg').upper()
  24. if not hashname.startswith('PGP-'):
  25. raise RuntimeError("micalg header does not start with PGP-")
  26. self.text, self.sig = message.get_payload()
  27. if self.sig.get_content_type() != 'application/pgp-signature':
  28. raise RuntimeError("second payload is not an application/pgp-signature payload")
  29. self.text_data = re.sub(r"\r?\n", "\r\n", self.text.as_string(False))
  30. self.sig_data = self.sig.get_payload()
  31. if not isinstance(self.sig_data, six.binary_type):
  32. raise RuntimeError("signature payload is not a byte string")
  33. return True
  34. elif message.is_multipart():
  35. for message in message.get_payload():
  36. if self._verify_rfc3156_email(message):
  37. return True
  38. return False
  39. else:
  40. return False