aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mailman_pgp/pgp/inline.py22
-rw-r--r--src/mailman_pgp/pgp/mime.py46
-rw-r--r--src/mailman_pgp/pgp/tests/data/inline_privkey.eml43
-rw-r--r--src/mailman_pgp/pgp/tests/data/inline_pubkey.eml30
-rw-r--r--src/mailman_pgp/pgp/tests/data/mime_privkey.eml59
-rw-r--r--src/mailman_pgp/pgp/tests/data/mime_pubkey.eml46
-rw-r--r--src/mailman_pgp/pgp/tests/test_inline.py35
-rw-r--r--src/mailman_pgp/pgp/tests/test_mime.py35
-rw-r--r--src/mailman_pgp/pgp/wrapper.py18
9 files changed, 319 insertions, 15 deletions
diff --git a/src/mailman_pgp/pgp/inline.py b/src/mailman_pgp/pgp/inline.py
index d87b3da..a8e8004 100644
--- a/src/mailman_pgp/pgp/inline.py
+++ b/src/mailman_pgp/pgp/inline.py
@@ -17,7 +17,7 @@
"""Strict inline PGP message wrapper."""
-from pgpy import PGPMessage
+from pgpy import PGPKey, PGPMessage
from pgpy.types import Armorable
from public import public
@@ -70,6 +70,26 @@ class InlineWrapper:
# XXX: This mistakes non-cleartext signature as encrypted.
return self._is_inline() and self._has_armor('MESSAGE')
+ def has_keys(self):
+ """
+ Whether the message contains public or private keys.
+
+ :return: If the message contains keys.
+ :rtype: bool
+ """
+ return self._is_inline() and (self._has_armor('PUBLIC KEY BLOCK') or
+ self._has_armor('PRIVATE KEY BLOCK'))
+
+ def keys(self):
+ """
+ Get the collection of keys in this message.
+
+ :return: A collection of keys.
+ """
+ # TODO: potentially return all things returned from from_blob?
+ key, _ = PGPKey.from_blob(self._as_string())
+ yield key
+
def verify(self, key):
"""
Verify the signature of this message with key.
diff --git a/src/mailman_pgp/pgp/mime.py b/src/mailman_pgp/pgp/mime.py
index fde9d49..3421167 100644
--- a/src/mailman_pgp/pgp/mime.py
+++ b/src/mailman_pgp/pgp/mime.py
@@ -16,10 +16,10 @@
# this program. If not, see <http://www.gnu.org/licenses/>.
"""RFC1847 and RFC3156 compliant message wrapped."""
-
+from email.iterators import walk
from email.utils import collapse_rfc2231_value
-from pgpy import PGPMessage, PGPSignature
+from pgpy import PGPKey, PGPMessage, PGPSignature
from public import public
@@ -29,6 +29,7 @@ class MIMEWrapper:
_signed_subtype = 'application/pgp-signature'
_encrypted_subtype = 'application/pgp-encrypted'
+ _keys_subtype = 'application/pgp-keys'
def __init__(self, msg):
"""
@@ -58,10 +59,9 @@ class MIMEWrapper:
protocol_param = collapse_rfc2231_value(self.msg.get_param('protocol'))
content_subtype = self.msg.get_content_subtype()
- return \
- second_type == MIMEWrapper._signed_subtype and \
- content_subtype == 'signed' and \
- protocol_param == MIMEWrapper._signed_subtype
+ return (second_type == MIMEWrapper._signed_subtype and
+ content_subtype == 'signed' and
+ protocol_param == MIMEWrapper._signed_subtype)
def is_encrypted(self):
"""
@@ -78,12 +78,34 @@ class MIMEWrapper:
content_subtype = self.msg.get_content_subtype()
protocol_param = collapse_rfc2231_value(self.msg.get_param('protocol'))
- return \
- 'Version: 1' in first_part and \
- first_type == MIMEWrapper._encrypted_subtype and \
- second_type == 'application/octet-stream' and \
- content_subtype == 'encrypted' and \
- protocol_param == MIMEWrapper._encrypted_subtype
+ return ('Version: 1' in first_part and
+ first_type == MIMEWrapper._encrypted_subtype and
+ second_type == 'application/octet-stream' and
+ content_subtype == 'encrypted' and
+ protocol_param == MIMEWrapper._encrypted_subtype)
+
+ def has_keys(self):
+ """
+ Whether the message contains keys as per RFC3156 section 7.
+
+ :return: If the message contains keys.
+ :rtype: bool
+ """
+ for part in walk(self.msg):
+ if part.get_content_type() == MIMEWrapper._keys_subtype:
+ return True
+ return False
+
+ def keys(self):
+ """
+ Get the collection of keys in this message.
+
+ :return: A collection of keys.
+ """
+ for part in walk(self.msg):
+ if part.get_content_type() == MIMEWrapper._keys_subtype:
+ key, _ = PGPKey.from_blob(part.get_payload())
+ yield key
def verify(self, key):
"""
diff --git a/src/mailman_pgp/pgp/tests/data/inline_privkey.eml b/src/mailman_pgp/pgp/tests/data/inline_privkey.eml
new file mode 100644
index 0000000..683efdd
--- /dev/null
+++ b/src/mailman_pgp/pgp/tests/data/inline_privkey.eml
@@ -0,0 +1,43 @@
+To: nobody@example.org
+From: RSA 1024b example <RSA-1024b@example.org>
+Subject: Some subject.
+Message-ID: <76a591ed-bfc4-d08b-73d3-fc2489148fd7@example.org>
+Date: Wed, 21 Jun 2017 13:50:59 +0200
+User-Agent: Mutt/1.7.2 (2016-11-26)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lQHYBFlKWqQBBADY8dCIub6x4tcFS3SmWW1r5ctwldFixkLz8LpBdgpc+zt7iWZI
+XvVWH9GYgTzgE+qEAVJcvQDG7/cX6zTopkkGEUmnwBgEFpc7Xi0D+/GYC23XleQk
+IF/R2Mf0AW3FBx/UxK0kIkYfTelkuZBrag83iLh3yKXkcLm1T010eGbTWQARAQAB
+AAP/ayABKrqZrQpHxfAMEmZ/TzPCIP6BzeX7wqxAtLlehapzJV3kGWF2gQgmPcm3
+byi2eWeTrYKQwytUVsXIswcFcCY1Fv6NkntMSqc6VJzGhvjKE9CTNJmgSjHlILMW
+Ma/9TzhxH2DT9tNMgOEN3+FoKRqjlLrhO/OiXqYZJdkXU+8CAOQin6DGnn+qvjlN
+5zw1GIpmWBt9b1S/WEqKaG1t4D/V0m0pAJBqeUbSC6MonQLA9pmIK/LbetUKRwM/
+xLNRMs8CAPNxR4NY73YIfSnlGRPdZHmOq4wMtqXYtoN1qZruHcXsrojcKHV72n8y
+Hb3R+LEKVjky95RKeKGowousIhGYQVcCAKsWtTWQA/VMW2V+ydzFHZHN0xwC9eTc
+uhs7G1qAqJR2POCq/0Cr3W4nXnbYSAr9wHal/YUuIKr54vNbPlXp6xqf/rQpUlNB
+IDEwMjRiIGV4YW1wbGUgPFJTQS0xMDI0YkBleGFtcGxlLm9yZz6IzgQTAQgAOBYh
+BNSpSIaxyiCWpkWOXEfxDAh4hLdYBQJZSlqkAhsDBQsJCAcCBhUICQoLAgQWAgMB
+Ah4BAheAAAoJEEfxDAh4hLdYbQIEALBwJUxkBGJYlP5kOZYAgQHw6+rwIgdXAoPk
+ldwcGPhvlBEocRYx+5KUYrx7W352dv+AgxSZ590JL7JGvWJDvMxoZGCJiRvJ7+Ve
+luKRH167wT8H4hxftBJqzorTU4eyPzG8bFneuag5dw+81DdngXjWRCorEHEdaQjc
+sfvVEmnhnQHYBFlKWqQBBADXLjeg+K0ZAuchhNkvMnfb8TlKoc1t1lH94unoqoj3
+L5Srf3XSo1fmuEBNr1nc5BLyH0tPDJZyuVCypfY4en9uaGvWO0U4t/OUiIWqPjBm
+XbjZWDdGKksb0cQNy13cvE57EmirbuVcXCE0OdU8lcbopN2wnecKOxLKK9PaLBZ6
+9wARAQABAAP+NyRiYA9p+GdciKPtLiGeQpA6EMyPAs8x2sB8FcIh8EpSrHIw5OYz
+/+2GmQHPIwKVclOfrmW45jRkICvUgZuurMmMrnDu63UT/9Pm+4EiUkPFnKfAgYFm
+XwWf2SklsoHCFT2WQ31WCp/hZxWucYqfPM/5ZsE+EAToK+C8BnMicI0CAOAUhruY
+JVh/7u6ES7xI6Hd7yHmU6rLr7oP2Z8cILirt5+1FgOP/qPdVEK9UGShbBcjfA+8W
+u4LISyuvCm8vuyMCAPXVJmTdmJjzBvP7BZe+HbDzWfhPCN+BvepGi3DQdHonLU2t
+IVOcMQsu0raaLevZ19nCKeMrOoAaIhCdjJUBGB0B/iSErQY+sNUAbjsW0zWovY2u
+e+0TBMDkO3OZCFKxCr/7mEuIfsAENXvDwAmx/YDklMwN8zgUAc5BqObGtRE7BYSg
+n4i2BBgBCAAgFiEE1KlIhrHKIJamRY5cR/EMCHiEt1gFAllKWqQCGwwACgkQR/EM
+CHiEt1gOwQP7BuyH2oKuWPAXcVrJdl3P3fIqvm4JzKRjXCVA9j5QOdihH1W5rZFC
+x3J+bUvKa1QJ1NuHoU9gYvR2NPs+CpMlTJ2wg7ksgtddlC9lsVi1ijvjJCugveBh
+a/CQJt7Cl6uDkifPsD5kxyUTecmnVfYZB6Fb/nrZxJ5Cb1dKPGixDpw=
+=e2xw
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/src/mailman_pgp/pgp/tests/data/inline_pubkey.eml b/src/mailman_pgp/pgp/tests/data/inline_pubkey.eml
new file mode 100644
index 0000000..cb0d176
--- /dev/null
+++ b/src/mailman_pgp/pgp/tests/data/inline_pubkey.eml
@@ -0,0 +1,30 @@
+To: nobody@example.org
+From: RSA 1024b example <RSA-1024b@example.org>
+Subject: Some subject.
+Message-ID: <76a591ed-bfc4-d08b-73d3-fc2489148fd7@example.org>
+Date: Wed, 21 Jun 2017 13:50:59 +0200
+User-Agent: Mutt/1.7.2 (2016-11-26)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 8bit
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mI0EWUpapAEEANjx0Ii5vrHi1wVLdKZZbWvly3CV0WLGQvPwukF2Clz7O3uJZkhe
+9VYf0ZiBPOAT6oQBUly9AMbv9xfrNOimSQYRSafAGAQWlzteLQP78ZgLbdeV5CQg
+X9HYx/QBbcUHH9TErSQiRh9N6WS5kGtqDzeIuHfIpeRwubVPTXR4ZtNZABEBAAG0
+KVJTQSAxMDI0YiBleGFtcGxlIDxSU0EtMTAyNGJAZXhhbXBsZS5vcmc+iM4EEwEI
+ADgWIQTUqUiGscoglqZFjlxH8QwIeIS3WAUCWUpapAIbAwULCQgHAgYVCAkKCwIE
+FgIDAQIeAQIXgAAKCRBH8QwIeIS3WG0CBACwcCVMZARiWJT+ZDmWAIEB8Ovq8CIH
+VwKD5JXcHBj4b5QRKHEWMfuSlGK8e1t+dnb/gIMUmefdCS+yRr1iQ7zMaGRgiYkb
+ye/lXpbikR9eu8E/B+IcX7QSas6K01OHsj8xvGxZ3rmoOXcPvNQ3Z4F41kQqKxBx
+HWkI3LH71RJp4biNBFlKWqQBBADXLjeg+K0ZAuchhNkvMnfb8TlKoc1t1lH94uno
+qoj3L5Srf3XSo1fmuEBNr1nc5BLyH0tPDJZyuVCypfY4en9uaGvWO0U4t/OUiIWq
+PjBmXbjZWDdGKksb0cQNy13cvE57EmirbuVcXCE0OdU8lcbopN2wnecKOxLKK9Pa
+LBZ69wARAQABiLYEGAEIACAWIQTUqUiGscoglqZFjlxH8QwIeIS3WAUCWUpapAIb
+DAAKCRBH8QwIeIS3WA7BA/sG7Ifagq5Y8BdxWsl2Xc/d8iq+bgnMpGNcJUD2PlA5
+2KEfVbmtkULHcn5tS8prVAnU24ehT2Bi9HY0+z4KkyVMnbCDuSyC112UL2WxWLWK
+O+MkK6C94GFr8JAm3sKXq4OSJ8+wPmTHJRN5yadV9hkHoVv+etnEnkJvV0o8aLEO
+nA==
+=4olM
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/src/mailman_pgp/pgp/tests/data/mime_privkey.eml b/src/mailman_pgp/pgp/tests/data/mime_privkey.eml
new file mode 100644
index 0000000..da66247
--- /dev/null
+++ b/src/mailman_pgp/pgp/tests/data/mime_privkey.eml
@@ -0,0 +1,59 @@
+To: nobody@example.org
+From: RSA 1024b example <RSA-1024b@example.org>
+Subject: Some subject.
+Message-ID: <76a591ed-bfc4-d08b-73d3-fc2489148fd7@example.org>
+Date: Wed, 21 Jun 2017 13:50:59 +0200
+User-Agent: Mutt/1.7.2 (2016-11-26)
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="------------A851F166D50529639139DD0B"
+
+This is a multi-part message in MIME format.
+--------------A851F166D50529639139DD0B
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+
+Some other text.
+
+--------------A851F166D50529639139DD0B
+Content-Type: application/pgp-keys;
+ name="0x7884B758.asc"
+Content-Transfer-Encoding: 7bit
+Content-Disposition: attachment;
+ filename="0x7884B758.asc"
+
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+
+lQHYBFlKWqQBBADY8dCIub6x4tcFS3SmWW1r5ctwldFixkLz8LpBdgpc+zt7iWZI
+XvVWH9GYgTzgE+qEAVJcvQDG7/cX6zTopkkGEUmnwBgEFpc7Xi0D+/GYC23XleQk
+IF/R2Mf0AW3FBx/UxK0kIkYfTelkuZBrag83iLh3yKXkcLm1T010eGbTWQARAQAB
+AAP/ayABKrqZrQpHxfAMEmZ/TzPCIP6BzeX7wqxAtLlehapzJV3kGWF2gQgmPcm3
+byi2eWeTrYKQwytUVsXIswcFcCY1Fv6NkntMSqc6VJzGhvjKE9CTNJmgSjHlILMW
+Ma/9TzhxH2DT9tNMgOEN3+FoKRqjlLrhO/OiXqYZJdkXU+8CAOQin6DGnn+qvjlN
+5zw1GIpmWBt9b1S/WEqKaG1t4D/V0m0pAJBqeUbSC6MonQLA9pmIK/LbetUKRwM/
+xLNRMs8CAPNxR4NY73YIfSnlGRPdZHmOq4wMtqXYtoN1qZruHcXsrojcKHV72n8y
+Hb3R+LEKVjky95RKeKGowousIhGYQVcCAKsWtTWQA/VMW2V+ydzFHZHN0xwC9eTc
+uhs7G1qAqJR2POCq/0Cr3W4nXnbYSAr9wHal/YUuIKr54vNbPlXp6xqf/rQpUlNB
+IDEwMjRiIGV4YW1wbGUgPFJTQS0xMDI0YkBleGFtcGxlLm9yZz6IzgQTAQgAOBYh
+BNSpSIaxyiCWpkWOXEfxDAh4hLdYBQJZSlqkAhsDBQsJCAcCBhUICQoLAgQWAgMB
+Ah4BAheAAAoJEEfxDAh4hLdYbQIEALBwJUxkBGJYlP5kOZYAgQHw6+rwIgdXAoPk
+ldwcGPhvlBEocRYx+5KUYrx7W352dv+AgxSZ590JL7JGvWJDvMxoZGCJiRvJ7+Ve
+luKRH167wT8H4hxftBJqzorTU4eyPzG8bFneuag5dw+81DdngXjWRCorEHEdaQjc
+sfvVEmnhnQHYBFlKWqQBBADXLjeg+K0ZAuchhNkvMnfb8TlKoc1t1lH94unoqoj3
+L5Srf3XSo1fmuEBNr1nc5BLyH0tPDJZyuVCypfY4en9uaGvWO0U4t/OUiIWqPjBm
+XbjZWDdGKksb0cQNy13cvE57EmirbuVcXCE0OdU8lcbopN2wnecKOxLKK9PaLBZ6
+9wARAQABAAP+NyRiYA9p+GdciKPtLiGeQpA6EMyPAs8x2sB8FcIh8EpSrHIw5OYz
+/+2GmQHPIwKVclOfrmW45jRkICvUgZuurMmMrnDu63UT/9Pm+4EiUkPFnKfAgYFm
+XwWf2SklsoHCFT2WQ31WCp/hZxWucYqfPM/5ZsE+EAToK+C8BnMicI0CAOAUhruY
+JVh/7u6ES7xI6Hd7yHmU6rLr7oP2Z8cILirt5+1FgOP/qPdVEK9UGShbBcjfA+8W
+u4LISyuvCm8vuyMCAPXVJmTdmJjzBvP7BZe+HbDzWfhPCN+BvepGi3DQdHonLU2t
+IVOcMQsu0raaLevZ19nCKeMrOoAaIhCdjJUBGB0B/iSErQY+sNUAbjsW0zWovY2u
+e+0TBMDkO3OZCFKxCr/7mEuIfsAENXvDwAmx/YDklMwN8zgUAc5BqObGtRE7BYSg
+n4i2BBgBCAAgFiEE1KlIhrHKIJamRY5cR/EMCHiEt1gFAllKWqQCGwwACgkQR/EM
+CHiEt1gOwQP7BuyH2oKuWPAXcVrJdl3P3fIqvm4JzKRjXCVA9j5QOdihH1W5rZFC
+x3J+bUvKa1QJ1NuHoU9gYvR2NPs+CpMlTJ2wg7ksgtddlC9lsVi1ijvjJCugveBh
+a/CQJt7Cl6uDkifPsD5kxyUTecmnVfYZB6Fb/nrZxJ5Cb1dKPGixDpw=
+=e2xw
+-----END PGP PRIVATE KEY BLOCK-----
+
+--------------A851F166D50529639139DD0B--
diff --git a/src/mailman_pgp/pgp/tests/data/mime_pubkey.eml b/src/mailman_pgp/pgp/tests/data/mime_pubkey.eml
new file mode 100644
index 0000000..1495a41
--- /dev/null
+++ b/src/mailman_pgp/pgp/tests/data/mime_pubkey.eml
@@ -0,0 +1,46 @@
+To: nobody@example.org
+From: RSA 1024b example <RSA-1024b@example.org>
+Subject: Some subject.
+Message-ID: <76a591ed-bfc4-d08b-73d3-fc2489148fd7@example.org>
+Date: Wed, 21 Jun 2017 13:50:59 +0200
+User-Agent: Mutt/1.7.2 (2016-11-26)
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="------------A851F166D50529639139DD0B"
+
+This is a multi-part message in MIME format.
+--------------A851F166D50529639139DD0B
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+
+Some other text.
+
+--------------A851F166D50529639139DD0B
+Content-Type: application/pgp-keys;
+ name="0x7884B758.asc"
+Content-Transfer-Encoding: 7bit
+Content-Disposition: attachment;
+ filename="0x7884B758.asc"
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mI0EWUpapAEEANjx0Ii5vrHi1wVLdKZZbWvly3CV0WLGQvPwukF2Clz7O3uJZkhe
+9VYf0ZiBPOAT6oQBUly9AMbv9xfrNOimSQYRSafAGAQWlzteLQP78ZgLbdeV5CQg
+X9HYx/QBbcUHH9TErSQiRh9N6WS5kGtqDzeIuHfIpeRwubVPTXR4ZtNZABEBAAG0
+KVJTQSAxMDI0YiBleGFtcGxlIDxSU0EtMTAyNGJAZXhhbXBsZS5vcmc+iM4EEwEI
+ADgWIQTUqUiGscoglqZFjlxH8QwIeIS3WAUCWUpapAIbAwULCQgHAgYVCAkKCwIE
+FgIDAQIeAQIXgAAKCRBH8QwIeIS3WG0CBACwcCVMZARiWJT+ZDmWAIEB8Ovq8CIH
+VwKD5JXcHBj4b5QRKHEWMfuSlGK8e1t+dnb/gIMUmefdCS+yRr1iQ7zMaGRgiYkb
+ye/lXpbikR9eu8E/B+IcX7QSas6K01OHsj8xvGxZ3rmoOXcPvNQ3Z4F41kQqKxBx
+HWkI3LH71RJp4biNBFlKWqQBBADXLjeg+K0ZAuchhNkvMnfb8TlKoc1t1lH94uno
+qoj3L5Srf3XSo1fmuEBNr1nc5BLyH0tPDJZyuVCypfY4en9uaGvWO0U4t/OUiIWq
+PjBmXbjZWDdGKksb0cQNy13cvE57EmirbuVcXCE0OdU8lcbopN2wnecKOxLKK9Pa
+LBZ69wARAQABiLYEGAEIACAWIQTUqUiGscoglqZFjlxH8QwIeIS3WAUCWUpapAIb
+DAAKCRBH8QwIeIS3WA7BA/sG7Ifagq5Y8BdxWsl2Xc/d8iq+bgnMpGNcJUD2PlA5
+2KEfVbmtkULHcn5tS8prVAnU24ehT2Bi9HY0+z4KkyVMnbCDuSyC112UL2WxWLWK
+O+MkK6C94GFr8JAm3sKXq4OSJ8+wPmTHJRN5yadV9hkHoVv+etnEnkJvV0o8aLEO
+nA==
+=4olM
+-----END PGP PUBLIC KEY BLOCK-----
+
+--------------A851F166D50529639139DD0B--
diff --git a/src/mailman_pgp/pgp/tests/test_inline.py b/src/mailman_pgp/pgp/tests/test_inline.py
index f8831c9..d144991 100644
--- a/src/mailman_pgp/pgp/tests/test_inline.py
+++ b/src/mailman_pgp/pgp/tests/test_inline.py
@@ -88,3 +88,38 @@ class TestEncryption(PGPTestCase, unittest.TestCase):
wrapped = self.wrapper(message)
self.assertEqual(wrapped.decrypt(key).message,
bytearray(clear, 'latin-1'))
+
+
+class TestKeys(PGPTestCase, unittest.TestCase):
+ def setUp(self):
+ self.wrapper = InlineWrapper
+
+ @parameterized.expand([
+ (load_message('data/inline_privkey.eml'),
+ True),
+ (load_message('data/inline_pubkey.eml'),
+ True),
+ (load_message('data/clear.eml'),
+ False),
+ (load_message('data/inline_signed.eml'),
+ False)
+ ])
+ def test_has_keys(self, message, has_keys):
+ wrapped = self.wrapper(message)
+ self.assertEqual(wrapped.has_keys(), has_keys)
+
+ @parameterized.expand([
+ (load_message('data/inline_privkey.eml'),
+ [load_key('data/rsa_1024.priv.asc')]),
+ (load_message('data/inline_pubkey.eml'),
+ [load_key('data/rsa_1024.pub.asc')])
+ ])
+ def test_keys(self, message, keys):
+ wrapped = self.wrapper(message)
+ loaded = list(wrapped.keys())
+ loaded_fingerprints = list(map(lambda key: key.fingerprint, loaded))
+
+ self.assertEqual(len(loaded), len(keys))
+
+ fingerprints = list(map(lambda key: key.fingerprint, keys))
+ self.assertListEqual(loaded_fingerprints, fingerprints)
diff --git a/src/mailman_pgp/pgp/tests/test_mime.py b/src/mailman_pgp/pgp/tests/test_mime.py
index cb8451d..8e00e9c 100644
--- a/src/mailman_pgp/pgp/tests/test_mime.py
+++ b/src/mailman_pgp/pgp/tests/test_mime.py
@@ -65,3 +65,38 @@ class TestEncryption(PGPTestCase, unittest.TestCase):
def test_decrypt(self):
pass
+
+
+class TestKeys(PGPTestCase, unittest.TestCase):
+ def setUp(self):
+ self.wrapper = MIMEWrapper
+
+ @parameterized.expand([
+ (load_message('data/mime_privkey.eml'),
+ True),
+ (load_message('data/mime_pubkey.eml'),
+ True),
+ (load_message('data/clear.eml'),
+ False),
+ (load_message('data/mime_signed.eml'),
+ False)
+ ])
+ def test_has_keys(self, message, has_keys):
+ wrapped = self.wrapper(message)
+ self.assertEqual(wrapped.has_keys(), has_keys)
+
+ @parameterized.expand([
+ (load_message('data/mime_privkey.eml'),
+ [load_key('data/rsa_1024.priv.asc')]),
+ (load_message('data/mime_pubkey.eml'),
+ [load_key('data/rsa_1024.pub.asc')])
+ ])
+ def test_keys(self, message, keys):
+ wrapped = self.wrapper(message)
+ loaded = list(wrapped.keys())
+ loaded_fingerprints = list(map(lambda key: key.fingerprint, loaded))
+
+ self.assertEqual(len(loaded), len(keys))
+
+ fingerprints = list(map(lambda key: key.fingerprint, keys))
+ self.assertListEqual(loaded_fingerprints, fingerprints)
diff --git a/src/mailman_pgp/pgp/wrapper.py b/src/mailman_pgp/pgp/wrapper.py
index 9a004c4..c6d8dff 100644
--- a/src/mailman_pgp/pgp/wrapper.py
+++ b/src/mailman_pgp/pgp/wrapper.py
@@ -57,7 +57,7 @@ class PGPWrapper():
"""
if self.is_mime_signed():
return self.mime.verify(key)
- else:
+ elif self.is_inline_signed():
return self.inline.verify(key)
def is_mime_encrypted(self):
@@ -80,5 +80,19 @@ class PGPWrapper():
"""
if self.is_mime_encrypted():
return self.mime.decrypt(key)
- else:
+ elif self.is_inline_encrypted():
return self.inline.decrypt(key)
+
+ def has_keys(self):
+ return self.mime.has_keys() or self.inline.has_keys()
+
+ def keys(self):
+ """
+ Get the collection of keys in this message.
+
+ :return: A collection of keys.
+ """
+ if self.mime.has_keys():
+ yield from self.mime.keys()
+ elif self.inline.has_keys():
+ yield from self.inline.keys()