aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/rsa.py14
-rw-r--r--src/cryptography/x509.py19
-rw-r--r--tests/conftest.py6
-rw-r--r--tests/hazmat/primitives/test_rsa.py16
-rw-r--r--tests/test_x509_ext.py18
5 files changed, 70 insertions, 3 deletions
diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py
index 89eac4d4..41b0089e 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -307,6 +307,17 @@ class RSAPrivateNumbers(object):
def __ne__(self, other):
return not self == other
+ def __hash__(self):
+ return hash((
+ self.p,
+ self.q,
+ self.d,
+ self.dmp1,
+ self.dmq1,
+ self.iqmp,
+ self.public_numbers,
+ ))
+
class RSAPublicNumbers(object):
def __init__(self, e, n):
@@ -336,3 +347,6 @@ class RSAPublicNumbers(object):
def __ne__(self, other):
return not self == other
+
+ def __hash__(self):
+ return hash((self.e, self.n))
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index 33c64168..8bed79e2 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -6,8 +6,11 @@ from __future__ import absolute_import, division, print_function
import abc
import ipaddress
+from email.utils import parseaddr
from enum import Enum
+import idna
+
import six
from cryptography import utils
@@ -901,7 +904,23 @@ class RFC822Name(object):
if not isinstance(value, six.text_type):
raise TypeError("value must be a unicode string")
+ name, address = parseaddr(value)
+ parts = address.split(u"@")
+ if name or not address:
+ # parseaddr has found a name (e.g. Name <email>) or the entire
+ # value is an empty string.
+ raise ValueError("Invalid rfc822name value")
+ elif len(parts) == 1:
+ # Single label email name. This is valid for local delivery.
+ # No IDNA encoding needed since there is no domain component.
+ encoded = address.encode("ascii")
+ else:
+ # A normal email of the form user@domain.com. Let's attempt to
+ # encode the domain component and reconstruct the address.
+ encoded = parts[0].encode("ascii") + b"@" + idna.encode(parts[1])
+
self._value = value
+ self._encoded = encoded
value = utils.read_only_property("_value")
diff --git a/tests/conftest.py b/tests/conftest.py
index 6599a643..bdd17fb7 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -12,10 +12,10 @@ from .utils import check_backend_support, select_backends, skip_if_empty
def pytest_generate_tests(metafunc):
- names = metafunc.config.getoption("--backend")
- selected_backends = select_backends(names, _available_backends())
-
if "backend" in metafunc.fixturenames:
+ names = metafunc.config.getoption("--backend")
+ selected_backends = select_backends(names, _available_backends())
+
filtered_backends = []
required = metafunc.function.requires_backend_interface
required_interfaces = [
diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py
index bfeab8dd..0c5f7042 100644
--- a/tests/hazmat/primitives/test_rsa.py
+++ b/tests/hazmat/primitives/test_rsa.py
@@ -1705,6 +1705,22 @@ class TestRSANumbersEquality(object):
)
assert num != object()
+ def test_public_numbers_hash(self):
+ pub1 = RSAPublicNumbers(3, 17)
+ pub2 = RSAPublicNumbers(3, 17)
+ pub3 = RSAPublicNumbers(7, 21)
+
+ assert hash(pub1) == hash(pub2)
+ assert hash(pub1) != hash(pub3)
+
+ def test_private_numbers_hash(self):
+ priv1 = RSAPrivateNumbers(1, 2, 3, 4, 5, 6, RSAPublicNumbers(1, 2))
+ priv2 = RSAPrivateNumbers(1, 2, 3, 4, 5, 6, RSAPublicNumbers(1, 2))
+ priv3 = RSAPrivateNumbers(1, 2, 3, 4, 5, 6, RSAPublicNumbers(1, 3))
+
+ assert hash(priv1) == hash(priv2)
+ assert hash(priv1) != hash(priv3)
+
class TestRSAPrimeFactorRecovery(object):
@pytest.mark.parametrize(
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index af0ffafb..84a40995 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -1087,6 +1087,24 @@ class TestDirectoryName(object):
assert gn != object()
+class TestRFC822Name(object):
+ def test_invalid_email(self):
+ with pytest.raises(ValueError):
+ x509.RFC822Name(u"Name <email>")
+
+ with pytest.raises(ValueError):
+ x509.RFC822Name(u"")
+
+ def test_single_label(self):
+ gn = x509.RFC822Name(u"administrator")
+ assert gn.value == u"administrator"
+
+ def test_idna(self):
+ gn = x509.RFC822Name(u"email@em\xe5\xefl.com")
+ assert gn.value == u"email@em\xe5\xefl.com"
+ assert gn._encoded == b"email@xn--eml-vla4c.com"
+
+
class TestRegisteredID(object):
def test_not_oid(self):
with pytest.raises(TypeError):