diff --git a/acme/acme/challenges.py b/acme/acme/challenges.py index e30c6452a..3b560ce44 100644 --- a/acme/acme/challenges.py +++ b/acme/acme/challenges.py @@ -15,6 +15,7 @@ from typing import Type from typing import TypeVar from typing import Union +from cryptography import x509 from cryptography.hazmat.primitives import hashes import josepy as jose from OpenSSL import crypto @@ -460,34 +461,41 @@ class TLSALPN01Response(KeyAuthorizationChallengeResponse): return crypto_util.probe_sni(host=host.encode(), port=port, name=domain.encode(), alpn_protocols=[self.ACME_TLS_1_PROTOCOL]) - def verify_cert(self, domain: str, cert: crypto.X509) -> bool: + def verify_cert(self, domain: str, cert: Union[x509.Certificate, crypto.X509]) -> bool: """Verify tls-alpn-01 challenge certificate. :param str domain: Domain name being validated. - :param OpensSSL.crypto.X509 cert: Challenge certificate. + :param cert: Challenge certificate. + :type cert: `cryptography.x509.Certificate` or `OpenSSL.crypto.X509` :returns: Whether the certificate was successfully verified. :rtype: bool """ - # pylint: disable=protected-access - names = crypto_util._pyopenssl_cert_or_req_all_names(cert) + if not isinstance(cert, x509.Certificate): + cert = cert.to_cryptography() + + names = crypto_util.get_names_from_subject_and_extensions( + cert.subject, cert.extensions + ) # Type ignore needed due to # https://github.com/pyca/pyopenssl/issues/730. - logger.debug('Certificate %s. SANs: %s', - cert.digest('sha256'), names) + logger.debug( + "Certificate %s. SANs: %s", cert.fingerprint(hashes.SHA256()), names + ) if len(names) != 1 or names[0].lower() != domain.lower(): return False - for i in range(cert.get_extension_count()): - ext = cert.get_extension(i) - # FIXME: assume this is the ACME extension. Currently there is no - # way to get full OID of an unknown extension from pyopenssl. - if ext.get_short_name() == b'UNDEF': - data = ext.get_data() - return data == self.h + try: + ext = cert.extensions.get_extension_for_oid( + x509.ObjectIdentifier(self.ID_PE_ACME_IDENTIFIER_V1.decode()) + ) + except x509.ExtensionNotFound: + return False - return False + # This is for the type checker. + assert isinstance(ext.value, x509.UnrecognizedExtension) + return ext.value.value == self.h # pylint: disable=too-many-arguments def simple_verify(self, chall: 'TLSALPN01', domain: str, account_public_key: jose.JWK,