add __hash__ to GeneralNames, SAN, IAN, and CertificateIssuer (#3916)

diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py
index 0bfe6f9..7a03139 100644
--- a/src/cryptography/x509/extensions.py
+++ b/src/cryptography/x509/extensions.py
@@ -1113,6 +1113,9 @@
     def __getitem__(self, idx):
         return self._general_names[idx]
 
+    def __hash__(self):
+        return hash(tuple(self._general_names))
+
 
 @utils.register_interface(ExtensionType)
 class SubjectAlternativeName(object):
@@ -1145,6 +1148,9 @@
     def __ne__(self, other):
         return not self == other
 
+    def __hash__(self):
+        return hash(self._general_names)
+
 
 @utils.register_interface(ExtensionType)
 class IssuerAlternativeName(object):
@@ -1177,6 +1183,9 @@
     def __getitem__(self, idx):
         return self._general_names[idx]
 
+    def __hash__(self):
+        return hash(self._general_names)
+
 
 @utils.register_interface(ExtensionType)
 class CertificateIssuer(object):
@@ -1209,6 +1218,9 @@
     def __getitem__(self, idx):
         return self._general_names[idx]
 
+    def __hash__(self):
+        return hash(self._general_names)
+
 
 @utils.register_interface(ExtensionType)
 class CRLReason(object):
diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py
index db805aa..d121a92 100644
--- a/tests/x509/test_x509_ext.py
+++ b/tests/x509/test_x509_ext.py
@@ -285,6 +285,15 @@
         names = ci.get_values_for_type(x509.DNSName)
         assert names == [u"cryptography.io"]
 
+    def test_hash(self):
+        ci1 = x509.CertificateIssuer([x509.DNSName(b"cryptography.io")])
+        ci2 = x509.CertificateIssuer([x509.DNSName(b"cryptography.io")])
+        ci3 = x509.CertificateIssuer(
+            [x509.UniformResourceIdentifier(b"http://something")]
+        )
+        assert hash(ci1) == hash(ci2)
+        assert hash(ci1) != hash(ci3)
+
 
 class TestCRLReason(object):
     def test_invalid_reason_flags(self):
@@ -2052,6 +2061,13 @@
         assert gns != gns2
         assert gns != object()
 
+    def test_hash(self):
+        gns = x509.GeneralNames([x509.DNSName(b"cryptography.io")])
+        gns2 = x509.GeneralNames([x509.DNSName(b"cryptography.io")])
+        gns3 = x509.GeneralNames([x509.RFC822Name(b"admin@cryptography.io")])
+        assert hash(gns) == hash(gns2)
+        assert hash(gns) != hash(gns3)
+
 
 class TestIssuerAlternativeName(object):
     def test_get_values_for_type(self):
@@ -2125,6 +2141,15 @@
         assert san != san2
         assert san != object()
 
+    def test_hash(self):
+        ian = x509.IssuerAlternativeName([x509.DNSName(b"cryptography.io")])
+        ian2 = x509.IssuerAlternativeName([x509.DNSName(b"cryptography.io")])
+        ian3 = x509.IssuerAlternativeName(
+            [x509.RFC822Name(b"admin@cryptography.io")]
+        )
+        assert hash(ian) == hash(ian2)
+        assert hash(ian) != hash(ian3)
+
 
 @pytest.mark.requires_backend_interface(interface=RSABackend)
 @pytest.mark.requires_backend_interface(interface=X509Backend)
@@ -2241,6 +2266,15 @@
         assert san != san2
         assert san != object()
 
+    def test_hash(self):
+        san = x509.SubjectAlternativeName([x509.DNSName(b"cryptography.io")])
+        san2 = x509.SubjectAlternativeName([x509.DNSName(b"cryptography.io")])
+        san3 = x509.SubjectAlternativeName(
+            [x509.RFC822Name(b"admin@cryptography.io")]
+        )
+        assert hash(san) == hash(san2)
+        assert hash(san) != hash(san3)
+
 
 @pytest.mark.requires_backend_interface(interface=RSABackend)
 @pytest.mark.requires_backend_interface(interface=X509Backend)