mirror of
https://github.com/certbot/certbot.git
synced 2026-06-08 16:22:18 -04:00
switch signature verification to use pure cryptography (#6000)
* switch signature verification to use pure cryptography On systems that prevent write/execute pages this prevents a segfault that is caused by pyopenssl creating a dynamic callback in the verification helper. * switch to using a verifier for older cryptography releases also add ec support, test vectors, and a test
This commit is contained in:
parent
36dfd06503
commit
366c50e28e
5 changed files with 61 additions and 9 deletions
|
|
@ -12,11 +12,16 @@ import os
|
|||
import pyrfc3339
|
||||
import six
|
||||
import zope.component
|
||||
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 OpenSSL import crypto
|
||||
from OpenSSL import SSL # type: ignore
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
# https://github.com/python/typeshed/tree/master/third_party/2/cryptography
|
||||
from cryptography import x509 # 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)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ CERT_PATH = test_util.vector_path('cert_512.pem')
|
|||
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 @@ class VerifyRenewableCertSigTest(VerifyCertSetup):
|
|||
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)
|
||||
|
|
|
|||
11
certbot/tests/testdata/cert-nosans_nistp256.pem
vendored
Normal file
11
certbot/tests/testdata/cert-nosans_nistp256.pem
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIBoDCCAUYCCQDCnzfUZ7TQdDAKBggqhkjOPQQDAjBYMQswCQYDVQQGEwJVUzER
|
||||
MA8GA1UECAwITWljaGlnYW4xEjAQBgNVBAcMCUFubiBBcmJvcjEMMAoGA1UECgwD
|
||||
RUZGMRQwEgYDVQQDDAtleGFtcGxlLmNvbTAeFw0xODA1MTUxNzIyMzlaFw0xODA2
|
||||
MTQxNzIyMzlaMFgxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNaWNoaWdhbjESMBAG
|
||||
A1UEBwwJQW5uIEFyYm9yMQwwCgYDVQQKDANFRkYxFDASBgNVBAMMC2V4YW1wbGUu
|
||||
Y29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPPl0JauSZukvAUWv4l5VNLAY
|
||||
QXhuPXYQBf4dVET3s0E5q9ZCbSe+pNUbko9F+TFkuc7XVjQPsfkDbh0I9nD0tzAK
|
||||
BggqhkjOPQQDAgNIADBFAiEAv8S2GXmWJqZ+j3DBfm72E1YK+HkOf+TOUHsbVR+O
|
||||
Z1oCIFWNt1SPdIgRp4QAyzVk2pcTF8jDNajEMLWETDtxgRvM
|
||||
-----END CERTIFICATE-----
|
||||
8
certbot/tests/testdata/csr-nosans_nistp256.pem
vendored
Normal file
8
certbot/tests/testdata/csr-nosans_nistp256.pem
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBFDCBugIBADBYMQswCQYDVQQGEwJVUzERMA8GA1UECAwITWljaGlnYW4xEjAQ
|
||||
BgNVBAcMCUFubiBBcmJvcjEMMAoGA1UECgwDRUZGMRQwEgYDVQQDDAtleGFtcGxl
|
||||
LmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDz5dCWrkmbpLwFFr+JeVTSw
|
||||
GEF4bj12EAX+HVRE97NBOavWQm0nvqTVG5KPRfkxZLnO11Y0D7H5A24dCPZw9Leg
|
||||
ADAKBggqhkjOPQQDAgNJADBGAiEAuoZHrYA5sy2DRTdLAxJTBNHKFFKbtaGt+QaJ
|
||||
A62qa8sCIQCUkSgSAiNaEnJ7r5fKphdjeORHqhpl6flYkLE3lGmGdg==
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
5
certbot/tests/testdata/nistp256_key.pem
vendored
Normal file
5
certbot/tests/testdata/nistp256_key.pem
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIOvXH384CyNNv2lfxvjc7hg2f7ScYoLvlk/VpINLJlGBoAoGCCqGSM49
|
||||
AwEHoUQDQgAEPPl0JauSZukvAUWv4l5VNLAYQXhuPXYQBf4dVET3s0E5q9ZCbSe+
|
||||
pNUbko9F+TFkuc7XVjQPsfkDbh0I9nD0tw==
|
||||
-----END EC PRIVATE KEY-----
|
||||
Loading…
Reference in a new issue