switch signature verification to use pure cryptography
diff --git a/certbot/crypto_util.py b/certbot/crypto_util.py
index b5ad16db14e..71f6c990c26 100644
--- a/certbot/crypto_util.py
+++ b/certbot/crypto_util.py
@@ -12,11 +12,16 @@
 import pyrfc3339
 import six
 import zope.component
-from OpenSSL import crypto
-from OpenSSL import SSL  # type: ignore
+from cryptography.exceptions import InvalidSignature
 from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives.asymmetric.ec import ECDSA
+from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePublicKey
+from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
+from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey
 # https://github.com/python/typeshed/tree/master/third_party/2/cryptography
-from cryptography import x509  # type: ignore
+from cryptography import x509 # type: ignore
+from OpenSSL import crypto
+from OpenSSL import SSL  # type: ignore
 
 from acme import crypto_util as acme_crypto_util
 from acme.magic_typing import IO  # pylint: disable=unused-import, no-name-in-module
@@ -228,13 +233,26 @@ def verify_renewable_cert_sig(renewable_cert):
     """
     try:
         with open(renewable_cert.chain, 'rb') as chain_file:  # type: IO[bytes]
-            chain, _ = pyopenssl_load_certificate(chain_file.read())
+            chain = x509.load_pem_x509_certificate(chain_file.read(), default_backend())
         with open(renewable_cert.cert, 'rb') as cert_file:  # type: IO[bytes]
-            cert = x509.load_pem_x509_certificate(
-                cert_file.read(), default_backend())
-        hash_name = cert.signature_hash_algorithm.name
-        crypto.verify(chain, cert.signature, cert.tbs_certificate_bytes, hash_name)
-    except (IOError, ValueError, crypto.Error) as e:
+            cert = x509.load_pem_x509_certificate(cert_file.read(), default_backend())
+        pk = chain.public_key()
+        if isinstance(pk, RSAPublicKey):
+            # https://github.com/python/typeshed/blob/master/third_party/2/cryptography/hazmat/primitives/asymmetric/rsa.pyi
+            verifier = pk.verifier(  # type: ignore
+                cert.signature, PKCS1v15(), cert.signature_hash_algorithm
+            )
+            verifier.update(cert.tbs_certificate_bytes)
+            verifier.verify()
+        elif isinstance(pk, EllipticCurvePublicKey):
+            verifier = pk.verifier(
+                cert.signature, ECDSA(cert.signature_hash_algorithm)
+            )
+            verifier.update(cert.tbs_certificate_bytes)
+            verifier.verify()
+        else:
+            raise errors.Error("Unsupported public key type")
+    except (IOError, ValueError, InvalidSignature) as e:
         error_str = "verifying the signature of the cert located at {0} has failed. \
                 Details: {1}".format(renewable_cert.cert, e)
         logger.exception(error_str)
diff --git a/certbot/tests/crypto_util_test.py b/certbot/tests/crypto_util_test.py
index 2fe0e3d30d5..baf14b2efad 100644
--- a/certbot/tests/crypto_util_test.py
+++ b/certbot/tests/crypto_util_test.py
@@ -21,6 +21,9 @@
 CERT = test_util.load_vector('cert_512.pem')
 SS_CERT_PATH = test_util.vector_path('cert_2048.pem')
 SS_CERT = test_util.load_vector('cert_2048.pem')
+P256_KEY = test_util.load_vector('nistp256_key.pem')
+P256_CERT_PATH = test_util.vector_path('cert-nosans_nistp256.pem')
+P256_CERT = test_util.load_vector('cert-nosans_nistp256.pem')
 
 class InitSaveKeyTest(test_util.TempDirTestCase):
     """Tests for certbot.crypto_util.init_save_key."""
@@ -217,6 +220,13 @@ def _call(self, renewable_cert):
     def test_cert_sig_match(self):
         self.assertEqual(None, self._call(self.renewable_cert))
 
+    def test_cert_sig_match_ec(self):
+        renewable_cert = mock.MagicMock()
+        renewable_cert.cert = P256_CERT_PATH
+        renewable_cert.chain = P256_CERT_PATH
+        renewable_cert.privkey = P256_KEY
+        self.assertEqual(None, self._call(renewable_cert))
+
     def test_cert_sig_mismatch(self):
         self.bad_renewable_cert.cert = test_util.vector_path('cert_512_bad.pem')
         self.assertRaises(errors.Error, self._call, self.bad_renewable_cert)
diff --git a/certbot/tests/testdata/cert-nosans_nistp256.pem b/certbot/tests/testdata/cert-nosans_nistp256.pem
new file mode 100644
index 00000000000..4ec3f24ce3d
--- /dev/null
+++ b/certbot/tests/testdata/cert-nosans_nistp256.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBoDCCAUYCCQDCnzfUZ7TQdDAKBggqhkjOPQQDAjBYMQswCQYDVQQGEwJVUzER
+MA8GA1UECAwITWljaGlnYW4xEjAQBgNVBAcMCUFubiBBcmJvcjEMMAoGA1UECgwD
+RUZGMRQwEgYDVQQDDAtleGFtcGxlLmNvbTAeFw0xODA1MTUxNzIyMzlaFw0xODA2
+MTQxNzIyMzlaMFgxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNaWNoaWdhbjESMBAG
+A1UEBwwJQW5uIEFyYm9yMQwwCgYDVQQKDANFRkYxFDASBgNVBAMMC2V4YW1wbGUu
+Y29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPPl0JauSZukvAUWv4l5VNLAY
+QXhuPXYQBf4dVET3s0E5q9ZCbSe+pNUbko9F+TFkuc7XVjQPsfkDbh0I9nD0tzAK
+BggqhkjOPQQDAgNIADBFAiEAv8S2GXmWJqZ+j3DBfm72E1YK+HkOf+TOUHsbVR+O
+Z1oCIFWNt1SPdIgRp4QAyzVk2pcTF8jDNajEMLWETDtxgRvM
+-----END CERTIFICATE-----
diff --git a/certbot/tests/testdata/csr-nosans_nistp256.pem b/certbot/tests/testdata/csr-nosans_nistp256.pem
new file mode 100644
index 00000000000..2f0a671ed94
--- /dev/null
+++ b/certbot/tests/testdata/csr-nosans_nistp256.pem
@@ -0,0 +1,8 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBFDCBugIBADBYMQswCQYDVQQGEwJVUzERMA8GA1UECAwITWljaGlnYW4xEjAQ
+BgNVBAcMCUFubiBBcmJvcjEMMAoGA1UECgwDRUZGMRQwEgYDVQQDDAtleGFtcGxl
+LmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDz5dCWrkmbpLwFFr+JeVTSw
+GEF4bj12EAX+HVRE97NBOavWQm0nvqTVG5KPRfkxZLnO11Y0D7H5A24dCPZw9Leg
+ADAKBggqhkjOPQQDAgNJADBGAiEAuoZHrYA5sy2DRTdLAxJTBNHKFFKbtaGt+QaJ
+A62qa8sCIQCUkSgSAiNaEnJ7r5fKphdjeORHqhpl6flYkLE3lGmGdg==
+-----END CERTIFICATE REQUEST-----
diff --git a/certbot/tests/testdata/nistp256_key.pem b/certbot/tests/testdata/nistp256_key.pem
new file mode 100644
index 00000000000..4be37e49bab
--- /dev/null
+++ b/certbot/tests/testdata/nistp256_key.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIOvXH384CyNNv2lfxvjc7hg2f7ScYoLvlk/VpINLJlGBoAoGCCqGSM49
+AwEHoUQDQgAEPPl0JauSZukvAUWv4l5VNLAYQXhuPXYQBf4dVET3s0E5q9ZCbSe+
+pNUbko9F+TFkuc7XVjQPsfkDbh0I9nD0tw==
+-----END EC PRIVATE KEY-----

On systems that prevent write/execute pages this prevents a segfault that is caused by pyopenssl creating a dynamic callback in the verification helper.