expand UniformResourceIdentiier to parse and internally IDNA encode
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index 8bed79e..58e1a37 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -13,6 +13,8 @@
 
 import six
 
+from six.moves import urllib_parse
+
 from cryptography import utils
 from cryptography.hazmat.primitives import hashes
 
@@ -966,7 +968,31 @@
         if not isinstance(value, six.text_type):
             raise TypeError("value must be a unicode string")
 
+        parsed = urllib_parse.urlparse(value)
+        if not parsed.hostname:
+            netloc = ""
+        elif parsed.port:
+            netloc = (
+                idna.encode(parsed.hostname) +
+                ":{0}".format(parsed.port).encode("ascii")
+            ).decode("ascii")
+        else:
+            netloc = idna.encode(parsed.hostname).decode("ascii")
+
+        # Note that building a URL in this fashion means it should be
+        # semantically indistinguishable from the original but is not
+        # guaranteed to be exactly the same.
+        uri = urllib_parse.urlunparse((
+            parsed.scheme,
+            netloc,
+            parsed.path,
+            parsed.params,
+            parsed.query,
+            parsed.fragment
+        )).encode("ascii")
+
         self._value = value
+        self._encoded = uri
 
     value = utils.read_only_property("_value")
 
diff --git a/tests/test_x509_ext.py b/tests/test_x509_ext.py
index 84a4099..7b13582 100644
--- a/tests/test_x509_ext.py
+++ b/tests/test_x509_ext.py
@@ -1105,6 +1105,38 @@
         assert gn._encoded == b"email@xn--eml-vla4c.com"
 
 
+class TestUniformResourceIdentifier(object):
+    def test_no_parsed_hostname(self):
+        gn = x509.UniformResourceIdentifier(u"singlelabel")
+        assert gn.value == u"singlelabel"
+
+    def test_with_port(self):
+        gn = x509.UniformResourceIdentifier(u"singlelabel:443/test")
+        assert gn.value == u"singlelabel:443/test"
+
+    def test_idna_no_port(self):
+        gn = x509.UniformResourceIdentifier(
+            u"http://\u043f\u044b\u043a\u0430.cryptography"
+        )
+        assert gn.value == u"http://\u043f\u044b\u043a\u0430.cryptography"
+        assert gn._encoded == b"http://xn--80ato2c.cryptography"
+
+    def test_idna_with_port(self):
+        gn = x509.UniformResourceIdentifier(
+            u"gopher://\u043f\u044b\u043a\u0430.cryptography:70/some/path"
+        )
+        assert gn.value == (
+            u"gopher://\u043f\u044b\u043a\u0430.cryptography:70/some/path"
+        )
+        assert gn._encoded == b"gopher://xn--80ato2c.cryptography:70/some/path"
+
+    def test_query_and_fragment(self):
+        gn = x509.UniformResourceIdentifier(
+            u"ldap://cryptography:90/path?query=true#somedata"
+        )
+        assert gn.value == u"ldap://cryptography:90/path?query=true#somedata"
+
+
 class TestRegisteredID(object):
     def test_not_oid(self):
         with pytest.raises(TypeError):