1.1 --- a/MoinMessage.py Tue Jun 04 14:59:47 2013 +0200
1.2 +++ b/MoinMessage.py Fri Jun 07 01:34:51 2013 +0200
1.3 @@ -162,6 +162,15 @@
1.4 class MoinMessageError(Exception):
1.5 pass
1.6
1.7 +class MoinMessageDecodingError(Exception):
1.8 + pass
1.9 +
1.10 +class MoinMessageMissingPart(MoinMessageDecodingError):
1.11 + pass
1.12 +
1.13 +class MoinMessageBadContent(MoinMessageDecodingError):
1.14 + pass
1.15 +
1.16 class GPG:
1.17
1.18 "A wrapper around the gpg command using a particular configuration."
1.19 @@ -216,7 +225,7 @@
1.20 cmd.stdout.close()
1.21 cmd.stderr.close()
1.22
1.23 - def verifyMessage(self, signature, content):
1.24 + def verifyMessageText(self, signature, content):
1.25
1.26 "Using the given 'signature', verify the given message 'content'."
1.27
1.28 @@ -266,6 +275,28 @@
1.29 os.remove(signature_filename)
1.30 os.remove(content_filename)
1.31
1.32 + def verifyMessage(self, message):
1.33 +
1.34 + """
1.35 + Verify the given RFC 3156 'message', returning a tuple of the form
1.36 + (fingerprint, identity, content).
1.37 + """
1.38 +
1.39 + try:
1.40 + content, signature = message.get_payload()
1.41 + except ValueError:
1.42 + raise MoinMessageMissingPart
1.43 +
1.44 + # Verify the message format.
1.45 +
1.46 + if signature.get_content_type() != "application/pgp-signature":
1.47 + raise MoinMessageBadContent
1.48 +
1.49 + # Verify the message.
1.50 +
1.51 + fingerprint, identity = self.verifyMessageText(signature.get_payload(), content.as_string())
1.52 + return fingerprint, identity, content
1.53 +
1.54 def signMessage(self, message, keyid):
1.55
1.56 """
1.57 @@ -286,12 +317,32 @@
1.58
1.59 return signed_message
1.60
1.61 - def decryptMessage(self, message):
1.62 + def decryptMessageText(self, message):
1.63
1.64 "Return a decrypted version of 'message'."
1.65
1.66 return self.run(["--decrypt"], message)
1.67
1.68 + def decryptMessage(self, message):
1.69 +
1.70 + """
1.71 + Decrypt the given RFC 3156 'message', returning the message text.
1.72 + """
1.73 +
1.74 + try:
1.75 + declaration, content = message.get_payload()
1.76 + except ValueError:
1.77 + raise MoinMessageMissingPart
1.78 +
1.79 + # Verify the message format.
1.80 +
1.81 + if content.get_content_type() != "application/octet-stream":
1.82 + raise MoinMessageBadContent
1.83 +
1.84 + # Return the decrypted message text.
1.85 +
1.86 + return self.decryptMessageText(content.get_payload())
1.87 +
1.88 def encryptMessage(self, message, keyid):
1.89
1.90 """
1.91 @@ -316,6 +367,25 @@
1.92
1.93 return encrypted_message
1.94
1.95 +# Message decoding functions.
1.96 +
1.97 +# Detect PGP/GPG-encoded payloads.
1.98 +# See: http://tools.ietf.org/html/rfc3156
1.99 +
1.100 +def is_signed(message):
1.101 + mimetype = message.get_content_type()
1.102 + encoding = message.get_content_charset()
1.103 +
1.104 + return mimetype == "multipart/signed" and \
1.105 + message.get_param("protocol") == "application/pgp-signature"
1.106 +
1.107 +def is_encrypted(message):
1.108 + mimetype = message.get_content_type()
1.109 + encoding = message.get_content_charset()
1.110 +
1.111 + return mimetype == "multipart/encrypted" and \
1.112 + message.get_param("protocol") == "application/pgp-encrypted"
1.113 +
1.114 # Communications functions.
1.115
1.116 def timestamp(message):