implement __hash__ on DistributionPoint and CRLDistributionPoints (#3915)

diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py
index 7a03139..442000e 100644
--- a/src/cryptography/x509/extensions.py
+++ b/src/cryptography/x509/extensions.py
@@ -412,6 +412,9 @@
     def __getitem__(self, idx):
         return self._distribution_points[idx]
 
+    def __hash__(self):
+        return hash(tuple(self._distribution_points))
+
 
 class DistributionPoint(object):
     def __init__(self, full_name, relative_name, reasons, crl_issuer):
@@ -487,6 +490,19 @@
     def __ne__(self, other):
         return not self == other
 
+    def __hash__(self):
+        if self.full_name is not None:
+            fn = tuple(self.full_name)
+        else:
+            fn = None
+
+        if self.crl_issuer is not None:
+            crl_issuer = tuple(self.crl_issuer)
+        else:
+            crl_issuer = None
+
+        return hash((fn, self.relative_name, self.reasons, crl_issuer))
+
     full_name = utils.read_only_property("_full_name")
     relative_name = utils.read_only_property("_relative_name")
     reasons = utils.read_only_property("_reasons")
diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py
index d121a92..b9400b6 100644
--- a/tests/x509/test_x509_ext.py
+++ b/tests/x509/test_x509_ext.py
@@ -3629,6 +3629,46 @@
                 ">)>])>"
             )
 
+    def test_hash(self):
+        dp = x509.DistributionPoint(
+            [x509.UniformResourceIdentifier(b"http://crypt.og/crl")],
+            None,
+            frozenset([x509.ReasonFlags.superseded]),
+            [
+                x509.DirectoryName(
+                    x509.Name([
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"Important CA"
+                        )
+                    ])
+                )
+            ],
+        )
+        dp2 = x509.DistributionPoint(
+            [x509.UniformResourceIdentifier(b"http://crypt.og/crl")],
+            None,
+            frozenset([x509.ReasonFlags.superseded]),
+            [
+                x509.DirectoryName(
+                    x509.Name([
+                        x509.NameAttribute(
+                            NameOID.COMMON_NAME, u"Important CA"
+                        )
+                    ])
+                )
+            ],
+        )
+        dp3 = x509.DistributionPoint(
+            None,
+            x509.RelativeDistinguishedName([
+                x509.NameAttribute(NameOID.COMMON_NAME, u"myCN")
+            ]),
+            None,
+            None,
+        )
+        assert hash(dp) == hash(dp2)
+        assert hash(dp) != hash(dp3)
+
 
 class TestCRLDistributionPoints(object):
     def test_invalid_distribution_points(self):
@@ -3780,6 +3820,40 @@
         assert cdp != cdp4
         assert cdp != object()
 
+    def test_hash(self):
+        cdp = x509.CRLDistributionPoints([
+            x509.DistributionPoint(
+                [x509.UniformResourceIdentifier(b"ftp://domain")],
+                None,
+                frozenset([
+                    x509.ReasonFlags.key_compromise,
+                    x509.ReasonFlags.ca_compromise,
+                ]),
+                [x509.UniformResourceIdentifier(b"uri://thing")],
+            ),
+        ])
+        cdp2 = x509.CRLDistributionPoints([
+            x509.DistributionPoint(
+                [x509.UniformResourceIdentifier(b"ftp://domain")],
+                None,
+                frozenset([
+                    x509.ReasonFlags.key_compromise,
+                    x509.ReasonFlags.ca_compromise,
+                ]),
+                [x509.UniformResourceIdentifier(b"uri://thing")],
+            ),
+        ])
+        cdp3 = x509.CRLDistributionPoints([
+            x509.DistributionPoint(
+                [x509.UniformResourceIdentifier(b"ftp://domain")],
+                None,
+                frozenset([x509.ReasonFlags.key_compromise]),
+                [x509.UniformResourceIdentifier(b"uri://thing")],
+            ),
+        ])
+        assert hash(cdp) == hash(cdp2)
+        assert hash(cdp) != hash(cdp3)
+
     def test_indexing(self):
         ci = x509.CRLDistributionPoints([
             x509.DistributionPoint(