def __init__(self, openssl_error_code: int) -> None: self.openssl_error_code = openssl_error_code self.openssl_error_string = X509.verify_cert_error_string( self.openssl_error_code) super().__init__( f'Verification failed with OpenSSL error code {self.openssl_error_code}: "{self.openssl_error_string}"' )
def verify(self, certificate_chain: List[X509]) -> List[X509]: """Validate a certificate chain and if successful, return the verified chain. The leaf certificate must be at index 0 of the certificate chain. WARNING: the validation logic does not perform hostname validation. """ if not certificate_chain: raise ValueError("Supplied an empty certificate chain") # Setup the context object for cert verification store_ctx = X509_STORE_CTX() store_ctx.set0_trusted_stack(self._trusted_certificates) store_ctx.set0_untrusted(certificate_chain) leaf_cert = certificate_chain[0] store_ctx.set_cert(leaf_cert) # Run the verification result: int = X509.verify_cert(store_ctx) if result == 1: # Validation succeeded verified_chain = store_ctx.get1_chain() return verified_chain elif result == 0: # Validation failed verify_result = store_ctx.get_error() raise CertificateChainVerificationFailed(verify_result) elif result < 0: raise RuntimeError("X509_verify_cert() was invoked incorrectly") else: raise RuntimeError( f"Result {result}; should never happen according to the OpenSSL documentation" )
def from_pem( cls, trusted_certificates_as_pem: List[str] ) -> "CertificateChainVerifier": if not trusted_certificates_as_pem: raise ValueError("Supplied an empty list of trusted certificates") return cls( [X509(cert_pem) for cert_pem in trusted_certificates_as_pem])
def _verify_certificate_chain(server_certificate_chain: List[str], trust_store: TrustStore) -> PathValidationResult: server_chain_as_x509s = [X509(pem_cert) for pem_cert in server_certificate_chain] chain_verifier = CertificateChainVerifier.from_file(trust_store.path) verified_chain: Optional[List[Certificate]] try: openssl_verify_str = None verified_chain_as_509s = chain_verifier.verify(server_chain_as_x509s) verified_chain = [ load_pem_x509_certificate(x509_cert.as_pem().encode("ascii"), backend=default_backend()) for x509_cert in verified_chain_as_509s ] except CertificateChainVerificationFailed as e: verified_chain = None openssl_verify_str = e.openssl_error_string return PathValidationResult( trust_store=trust_store, verified_certificate_chain=verified_chain, openssl_error_string=openssl_verify_str )
def certificate_as_x509() -> X509: pem_cert = """-----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp 1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE 38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE-----""" return X509(pem_cert)
def get_certificate_chain_verify_result(self): verifyResult = self._ssl.get_verify_result() verifyResultStr = X509.verify_cert_error_string(verifyResult) return verifyResult, verifyResultStr
def get_certificate_chain_verify_result(self) -> Tuple[int, str]: verify_result = self._ssl.get_verify_result() verify_result_str = X509.verify_cert_error_string(verify_result) return verify_result, verify_result_str
def test_expired_certificate_chain(self): expired_leaf = """-----BEGIN CERTIFICATE----- MIIFSzCCBDOgAwIBAgIQSueVSfqavj8QDxekeOFpCTANBgkqhkiG9w0BAQsFADCB kDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxNjA0BgNV BAMTLUNPTU9ETyBSU0EgRG9tYWluIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZlciBD QTAeFw0xNTA0MDkwMDAwMDBaFw0xNTA0MTIyMzU5NTlaMFkxITAfBgNVBAsTGERv bWFpbiBDb250cm9sIFZhbGlkYXRlZDEdMBsGA1UECxMUUG9zaXRpdmVTU0wgV2ls ZGNhcmQxFTATBgNVBAMUDCouYmFkc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAMIE7PiM7gTCs9hQ1XBYzJMY61yoaEmwIrX5lZ6xKyx2PmzA S2BMTOqytMAPgLaw+XLJhgL5XEFdEyt/ccRLvOmULlA3pmccYYz2QULFRtMWhyef dOsKnRFSJiFzbIRMeVXk0WvoBj1IFVKtsyjbqv9u/2CVSndrOfEk0TG23U3AxPxT uW1CrbV8/q71FdIzSOciccfCFHpsKOo3St/qbLVytH5aohbcabFXRNsKEqveww9H dFxBIuGa+RuT5q0iBikusbpJHAwnnqP7i/dAcgCskgjZjFeEU4EFy+b+a1SYQCeF xxC7c3DvaRhBB0VVfPlkPz0sw6l865MaTIbRyoUCAwEAAaOCAdUwggHRMB8GA1Ud IwQYMBaAFJCvajqUWgvYkOoSVnPfQ7Q6KNrnMB0GA1UdDgQWBBSd7sF7gQs6R2lx GH0RN5O8pRs/+zAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUE FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTwYDVR0gBEgwRjA6BgsrBgEEAbIxAQIC BzArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQUzAI BgZngQwBAgEwVAYDVR0fBE0wSzBJoEegRYZDaHR0cDovL2NybC5jb21vZG9jYS5j b20vQ09NT0RPUlNBRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCB hQYIKwYBBQUHAQEEeTB3ME8GCCsGAQUFBzAChkNodHRwOi8vY3J0LmNvbW9kb2Nh LmNvbS9DT01PRE9SU0FEb21haW5WYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0 MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wIwYDVR0RBBww GoIMKi5iYWRzc2wuY29tggpiYWRzc2wuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBq evHa/wMHcnjFZqFPRkMOXxQhjHUa6zbgH6QQFezaMyV8O7UKxwE4PSf9WNnM6i1p OXy+l+8L1gtY54x/v7NMHfO3kICmNnwUW+wHLQI+G1tjWxWrAPofOxkt3+IjEBEH fnJ/4r+3ABuYLyw/zoWaJ4wQIghBK4o+gk783SHGVnRwpDTysUCeK1iiWQ8dSO/r ET7BSp68ZVVtxqPv1dSWzfGuJ/ekVxQ8lEEFeouhN0fX9X3c+s5vMaKwjOrMEpsi 8TRwz311SotoKQwe6Zaoz7ASH1wq7mcvf71z81oBIgxw+s1F73hczg36TuHvzmWf RwxPuzZEaFZcVlmtqoq8 -----END CERTIFICATE-----""" expired_intermediate = """-----BEGIN CERTIFICATE----- MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMjEy MDAwMDAwWhcNMjkwMjExMjM1OTU5WjCBkDELMAkGA1UEBhMCR0IxGzAZBgNVBAgT EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR Q09NT0RPIENBIExpbWl0ZWQxNjA0BgNVBAMTLUNPTU9ETyBSU0EgRG9tYWluIFZh bGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAI7CAhnhoFmk6zg1jSz9AdDTScBkxwtiBUUWOqigwAwCfx3M28Sh bXcDow+G+eMGnD4LgYqbSRutA776S9uMIO3Vzl5ljj4Nr0zCsLdFXlIvNN5IJGS0 Qa4Al/e+Z96e0HqnU4A7fK31llVvl0cKfIWLIpeNs4TgllfQcBhglo/uLQeTnaG6 ytHNe+nEKpooIZFNb5JPJaXyejXdJtxGpdCsWTWM/06RQ1A/WZMebFEh7lgUq/51 UHg+TLAchhP6a5i84DuUHoVS3AOTJBhuyydRReZw3iVDpA3hSqXttn7IzW3uLh0n c13cRTCAquOyQQuvvUSH2rnlG51/ruWFgqUCAwEAAaOCAWUwggFhMB8GA1UdIwQY MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBSQr2o6lFoL2JDqElZz 30O0Oija5zAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgG BmeBDAECATBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv bS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcB AQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9E T1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAE4rdk+SHGI2ibp3wScF9BzWRJ2p mj6q1WZmAT7qSeaiNbz69t2Vjpk1mA42GHWx3d1Qcnyu3HeIzg/3kCDKo2cuH1Z/ e+FE6kKVxF0NAVBGFfKBiVlsit2M8RKhjTpCipj4SzR7JzsItG8kO3KdY3RYPBps P0/HEZrIqPW1N+8QRcZs2eBelSaz662jue5/DJpmNXMyYE7l3YphLG5SEXdoltMY dVEVABt0iN3hxzgEQyjpFv3ZBdRdRydg1vs4O2xyopT4Qhrf7W8GjEXCBgCq5Ojc 2bXhc3js9iPc0d1sjhqPpepUfJa3w/5Vjo1JXvxku88+vZbrac2/4EjxYoIQ5QxG V/Iz2tDIY+3GH5QFlkoakdH368+PUq4NCNk+qKBR6cGHdNXJ93SrLlP7u3r7l+L4 HyaPs9Kg4DdbKDsx5Q5XLVq4rXmsXiBmGqW5prU5wfWYQ//u+aen/e7KJD2AFsQX j4rBYKEMrltDR5FL1ZoXX/nUh8HCjLfn4g8wGTeGrODcQgPmlKidrv0PJFGUzpII 0fxQ8ANAe4hZ7Q7drNJ3gjTcBpUC2JD5Leo31Rpg0Gcg19hCC0Wvgmje3WYkN5Ap lBlGGSW4gNfL1IYoakRwJiNiqZ+Gb7+6kHDSVneFeO/qJakXzlByjAA6quPbYzSf +AZxAeKCINT+b72x -----END CERTIFICATE-----""" path_validator = CertificateChainVerifier.from_file( Path(__file__).absolute().parent / "mozilla.pem") try: path_validator.verify( [X509(expired_leaf), X509(expired_intermediate)]) except CertificateChainVerificationFailed as e: assert 10 == e.openssl_error_code # 10 is the error code for an expired certificate assert e.openssl_error_string
def certificate_chain_as_x509() -> List[X509]: leaf_pem = """-----BEGIN CERTIFICATE----- MIII9DCCBtygAwIBAgITEgAU8ewjldVv3MTctwAAABTx7DANBgkqhkiG9w0BAQsF ADBPMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u MSAwHgYDVQQDExdNaWNyb3NvZnQgUlNBIFRMUyBDQSAwMTAeFw0yMTA3MjgyMTIy MDZaFw0yMjA3MjgyMTIyMDZaMIGIMQswCQYDVQQGEwJVUzELMAkGA1UECBMCV0Ex EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv bjEeMBwGA1UECxMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMRowGAYDVQQDExF3d3cu bWljcm9zb2Z0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMnE YTuMHAC05tDE3Xeql1wP18DqLF1YZ6z6vsnmS9FQg5HhjYW9d5JEpxldYfA26Rmu SjzBnPIV6C9TsxSasdijXzMBGBXLMRN1Lqo8t+ULT0JAsmt0TjvhGTk7qAWOxx5W gbEA+hZP12P1glre2E5LGORyf3/HDDHDJpoyVrJQcXTTxGGFrUaz8BxpSxnk3+p+ /b2hPxO70jt3vqtpgS+dJa9j9CsGm5f6QZdYFCNVL3HNk4ji36dQZd3Z01jjddgn 8eqG220HvEDL+tJY+q9/iz0fLd+rcDO/igCgpEfM3/gmz4b9xUB1MfexdFNX8zxq 7HBedJTQOSrYbcEupCMCAwEAAaOCBI0wggSJMIIBfAYKKwYBBAHWeQIEAgSCAWwE ggFoAWYAdQApeb7wnjk5IfBWc59jpXflvld9nGAK+PlNXSZcJV3HhAAAAXrvCDQo AAAEAwBGMEQCIGsG4F9acHkVtLDESPJxtX8xga3P+ib5mF86uhDdHdQyAiAIlmPH 81f0tFDjOT3QypOpS6W95Wv4AB7QpxQPkX5R+wB1AEHIyrHfIkZKEMahOglCh15O MYsbA+vrS8do8JBilgb2AAABeu8INBYAAAQDAEYwRAIgYLmw/lgwOh/iFUG+ghFb jH9odXbXMn9pH+6aoOwNpJoCIFOT/s390eZjaTM99x3B+7aF2iah+3NbIVRIO7eU gCUJAHYARqVV63X6kSAwtaKJafTzfREsQXS+/Um4havy/HD+bUcAAAF67wg0VQAA BAMARzBFAiEAvkCi3Cm3jnqCQFRVP4cinZcVZbMVsIsCdWq17Ql9W7gCIFsGi8PI T+LMgAOXRfRyq4o5ffWlrF3RKPjpFm1XmcvaMCcGCSsGAQQBgjcVCgQaMBgwCgYI KwYBBQUHAwIwCgYIKwYBBQUHAwEwPQYJKwYBBAGCNxUHBDAwLgYmKwYBBAGCNxUI h9qGdYPu2QGCyYUbgbWeYYX062CBXbn4EIaR0HgCAWQCASUwgYcGCCsGAQUFBwEB BHsweTBTBggrBgEFBQcwAoZHaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraS9t c2NvcnAvTWljcm9zb2Z0JTIwUlNBJTIwVExTJTIwQ0ElMjAwMS5jcnQwIgYIKwYB BQUHMAGGFmh0dHA6Ly9vY3NwLm1zb2NzcC5jb20wHQYDVR0OBBYEFAkmLKnc/2OR QOdYZ+IIP3T26vFlMA4GA1UdDwEB/wQEAwIEsDCBmQYDVR0RBIGRMIGOghVwcml2 YWN5Lm1pY3Jvc29mdC5jb22CEWMucy1taWNyb3NvZnQuY29tgg1taWNyb3NvZnQu Y29tghFpLnMtbWljcm9zb2Z0LmNvbYIYc3RhdGljdmlldy5taWNyb3NvZnQuY29t ghF3d3cubWljcm9zb2Z0LmNvbYITd3d3cWEubWljcm9zb2Z0LmNvbTCBsAYDVR0f BIGoMIGlMIGioIGfoIGchk1odHRwOi8vbXNjcmwubWljcm9zb2Z0LmNvbS9wa2kv bXNjb3JwL2NybC9NaWNyb3NvZnQlMjBSU0ElMjBUTFMlMjBDQSUyMDAxLmNybIZL aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9tc2NvcnAvY3JsL01pY3Jvc29m dCUyMFJTQSUyMFRMUyUyMENBJTIwMDEuY3JsMFcGA1UdIARQME4wQgYJKwYBBAGC NyoBMDUwMwYIKwYBBQUHAgEWJ2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kv bXNjb3JwL2NwczAIBgZngQwBAgIwHwYDVR0jBBgwFoAUtXYMMBHOx5JCTUzHXCzI qQzoC2QwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA0GCSqGSIb3DQEB CwUAA4ICAQAVMIWmZCVQqfj7bJx9qruDL8/ylrr3axGTW38+QbP7a+705e8piKYA oSLpwDnWs00JzLLfe55xE7b3veY5q88ZAcQfB34tvewp+2rYvTcvPq641TXloQlJ an/90VgkCa2YsbSwWg4uldv0fjvbdZmRvm/fofrR45ySK8KK1SsNJ1Aa/3wuNCyj L03dT3tf2pDymMaNj3PamyjClHsdYcWop3ZBbM/PiL0pY/a0YsqIUsUkpK93yC4E +IkZkQDEEAeZHzoHlZv2moJSKL357z1wqS2tDTNGpX8NBvudKkUlnShJfu6MFn1m vXONhYfpYpJ5t0DxFwhahPS7MKmp/sz7A5fO8b/nvyvwohvHHlI502Np7LdRWE1J 7bNmOcCK/gGVWU2VtZUyhJwGN104Aba61Jn8+mds8JagLPAwiB2Si7M1sfKHpacC GTeO2N8v8WaBQw/hFLnXlV6c8C8QrYLWLxlmM+6pAlm9fHVU4RESJFseMJiJ66US bKVIwfysnXZseCb5gbVI8v3d/qpPZSkpKfLs47spTDVKEqSBr8a2evyRJFzIZZ0v MW9by1fTuByXk82Uyz6/MQ4x0Z/zflGSOyozpZFli7FMFbh4+Fpg6s5RgWVVep96 h4MER2f+ulxJ3j9wUxCa/BR6St/Ck6ZO+FL676uHMx3NMrrSVltSuA== -----END CERTIFICATE----- """ intermediate_pem = """-----BEGIN CERTIFICATE----- MIIFWjCCBEKgAwIBAgIQDxSWXyAgaZlP1ceseIlB4jANBgkqhkiG9w0BAQsFADBa MQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJl clRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTIw MDcyMTIzMDAwMFoXDTI0MTAwODA3MDAwMFowTzELMAkGA1UEBhMCVVMxHjAcBgNV BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEgMB4GA1UEAxMXTWljcm9zb2Z0IFJT QSBUTFMgQ0EgMDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqYnfP mmOyBoTzkDb0mfMUUavqlQo7Rgb9EUEf/lsGWMk4bgj8T0RIzTqk970eouKVuL5R IMW/snBjXXgMQ8ApzWRJCZbar879BV8rKpHoAW4uGJssnNABf2n17j9TiFy6BWy+ IhVnFILyLNK+W2M3zK9gheiWa2uACKhuvgCca5Vw/OQYErEdG7LBEzFnMzTmJcli W1iCdXby/vI/OxbfqkKD4zJtm45DJvC9Dh+hpzqvLMiK5uo/+aXSJY+SqhoIEpz+ rErHw+uAlKuHFtEjSeeku8eR3+Z5ND9BSqc6JtLqb0bjOHPm5dSRrgt4nnil75bj c9j3lWXpBb9PXP9Sp/nPCK+nTQmZwHGjUnqlO9ebAVQD47ZisFonnDAmjrZNVqEX F3p7laEHrFMxttYuD81BdOzxAbL9Rb/8MeFGQjE2Qx65qgVfhH+RsYuuD9dUw/3w ZAhq05yO6nk07AM9c+AbNtRoEcdZcLCHfMDcbkXKNs5DJncCqXAN6LhXVERCw/us G2MmCMLSIx9/kwt8bwhUmitOXc6fpT7SmFvRAtvxg84wUkg4Y/Gx++0j0z6StSeN 0EJz150jaHG6WV4HUqaWTb98Tm90IgXAU4AW2GBOlzFPiU5IY9jt+eXC2Q6yC/Zp TL1LAcnL3Qa/OgLrHN0wiw1KFGD51WRPQ0Sh7QIDAQABo4IBJTCCASEwHQYDVR0O BBYEFLV2DDARzseSQk1Mx1wsyKkM6AtkMB8GA1UdIwQYMBaAFOWdWTCCR1jMrPoI VDaGezq1BE3wMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYI KwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADA0BggrBgEFBQcBAQQoMCYwJAYI KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTA6BgNVHR8EMzAxMC+g LaArhilodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vT21uaXJvb3QyMDI1LmNybDAq BgNVHSAEIzAhMAgGBmeBDAECATAIBgZngQwBAgIwCwYJKwYBBAGCNyoBMA0GCSqG SIb3DQEBCwUAA4IBAQCfK76SZ1vae4qt6P+dTQUO7bYNFUHR5hXcA2D59CJWnEj5 na7aKzyowKvQupW4yMH9fGNxtsh6iJswRqOOfZYC4/giBO/gNsBvwr8uDW7t1nYo DYGHPpvnpxCM2mYfQFHq576/TmeYu1RZY29C4w8xYBlkAA8mDJfRhMCmehk7cN5F JtyWRj2cZj/hOoI45TYDBChXpOlLZKIYiG1giY16vhCRi6zmPzEwv+tk156N6cGS Vm44jTQ/rs1sa0JSYjzUaYngoFdZC4OfxnIkQvUIA4TOFmPzNPEFdjcZsgbeEz4T cGHTBPK4R28F44qIMCtHRV55VMX53ev6P3hRddJb -----END CERTIFICATE----- """ return [X509(leaf_pem), X509(intermediate_pem)]
def certificate_chain_as_x509() -> List[X509]: leaf_pem = """-----BEGIN CERTIFICATE----- MIIJHzCCBwegAwIBAgITLQAMNxVixB2TlAh/aAAAAAw3FTANBgkqhkiG9w0BAQsF ADCBizELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEVMBMGA1UE CxMMTWljcm9zb2Z0IElUMR4wHAYDVQQDExVNaWNyb3NvZnQgSVQgVExTIENBIDUw HhcNMTkxMDIxMjIwNDA0WhcNMjExMDIxMjIwNDA0WjCBiDELMAkGA1UEBhMCVVMx CzAJBgNVBAgTAldBMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv ZnQgQ29ycG9yYXRpb24xHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEa MBgGA1UEAxMRd3d3Lm1pY3Jvc29mdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB DwAwggEKAoIBAQDTEK1CzUwdArEOb/vDOqds7/vQ1yGQtAYaZYNBch27Kw3/XKnf td3NVj7tYe7MhI1U+bknxhSx7m4ti7Pzt6mxQiTZ/KegYhxosd3sOEikXgJVzECv h0Mvd6adrvi00cUeQz0dlkUkuxMAjiFs+FX7Ogf4xt8ub4hKZPGB85vDnQQ0OHVh L9IuUbYHhmh8EoDEdR+og+lj7u5OKt3YEWntgbnfV1d66U59kfp5Dg4T/zFjqz/l U3KGBWgj0YoxH8KGfuq2YfFQsm7Q4MDJnR2PNUbwwrK5JldcRn27o5SVZxaB55bs dyHWL0GbG5JoIIWg8pGJXKYGfARDEVjWijBPAgMBAAGjggR7MIIEdzCCAXwGCisG AQQB1nkCBAIEggFsBIIBaAFmAHYA9lyUL9F3MCIUVBgIMJRWjuNNExkzv98MLyAL zE7xZOMAAAFt8GJxcQAABAMARzBFAiEAldKDzhaLTJ1PpTpE7TmrRp+nDwoEZbW5 JOfrPKoR6PsCIBOqc6bzu7MnferBbxkUKwS67LpFTJgxYk6RV98m5fK2AHUAVYHU whaQNgFK6gubVzxT8MDkOHhwJQgXL6OqHQcT0wwAAAFt8GJyzQAABAMARjBEAiBa JqHGYrk+yh3ccuelsJxqLbhE3DJuSBZxe+xEpiabhQIgRdcckht/x8uG6tSrRKg5 0GdwnWlFKMBDT50rQjIPflMAdQB9PvL4j/+IVWgkwsDKnlKJeSvFDngJfy5ql2iZ fiLw1wAAAW3wYnG7AAAEAwBGMEQCIGToqXolvHTes1f0QwV9RSvEE5HVwX6jn70+ KaExl0+BAiBosObeHSU867FO1Aw5dw+R01ZZ1fudHxDwuXgLvqFmQzAnBgkrBgEE AYI3FQoEGjAYMAoGCCsGAQUFBwMCMAoGCCsGAQUFBwMBMD4GCSsGAQQBgjcVBwQx MC8GJysGAQQBgjcVCIfahnWD7tkBgsmFG4G1nmGF9OtggV2E0t9CgueTegIBZAIB HTCBhQYIKwYBBQUHAQEEeTB3MFEGCCsGAQUFBzAChkVodHRwOi8vd3d3Lm1pY3Jv c29mdC5jb20vcGtpL21zY29ycC9NaWNyb3NvZnQlMjBJVCUyMFRMUyUyMENBJTIw NS5jcnQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLm1zb2NzcC5jb20wHQYDVR0O BBYEFParvwUeQbdw6ZH4GpVu9gwrCfuVMAsGA1UdDwQEAwIEsDCBmQYDVR0RBIGR MIGOghN3d3dxYS5taWNyb3NvZnQuY29tghF3d3cubWljcm9zb2Z0LmNvbYIYc3Rh dGljdmlldy5taWNyb3NvZnQuY29tghFpLnMtbWljcm9zb2Z0LmNvbYINbWljcm9z b2Z0LmNvbYIRYy5zLW1pY3Jvc29mdC5jb22CFXByaXZhY3kubWljcm9zb2Z0LmNv bTCBrAYDVR0fBIGkMIGhMIGeoIGboIGYhktodHRwOi8vbXNjcmwubWljcm9zb2Z0 LmNvbS9wa2kvbXNjb3JwL2NybC9NaWNyb3NvZnQlMjBJVCUyMFRMUyUyMENBJTIw NS5jcmyGSWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvbXNjb3JwL2NybC9N aWNyb3NvZnQlMjBJVCUyMFRMUyUyMENBJTIwNS5jcmwwTQYDVR0gBEYwRDBCBgkr BgEEAYI3KgEwNTAzBggrBgEFBQcCARYnaHR0cDovL3d3dy5taWNyb3NvZnQuY29t L3BraS9tc2NvcnAvY3BzMB8GA1UdIwQYMBaAFAj+JZ906ocEwry7jqg4XzPG0Wxl MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOC AgEAdWMaW3NOP5Yr47Sow1UZNLMmDlxNjz+8DcHiflQfKsImOvs/UflUrMGXG7rH 57NbJZ9nYpSTHWxSJfKsGPc3pgc5R1sxZxDb6lBuXEN9NvhJMmPwBkyKJAAnjYN6 yCNZP4X6dBOONW8uopknF+CRHDZdSiMaFiE4fVCe0LrO90b4ROPsRV8zHn57i1B1 69n1cqsLXrMHvK0Xnu7rwrvvd5BbOaqm7DrgwJYUk0UciNEfcyN2dNRcCxofWQdV GQqvagqtjyDCm/EJ6DJ2kWllGHjauc8IkMaUeCedTYphChEckXoRBZikZtyL0oZj 67iKht6mm4fST+x0Zuu5wdzUoCTQsNTHV0GSbcVIRcgmaNiwP+0+lrRocUrj2h/7 2IQN8Pe/+CrDeVJNlKA9gWNl+t1F/r3CKWnkENyNUCTggiCSojdY9Rkj1rTieP6M SBUZBWf3MB5XIuaLOTO0/whM831krxNG/k0mdCpDtdKvCKIcARrkKM9A3TxtVpOd 8f9kifcGaPqTQYr8fxhrNB864qsCG17o8ZckBKW8FY5H/jSQAZb1qbwsTbBMXJIr 0lAPwH7LIAHJJyslG0X3Mp0ARumGWqVwiHOCaLXO1iSQX0wW4yo+lGxWONvOIoad 2Ned/fxM675fEVC+r+DI6BKbt9ChfIXiXeULqOZC3yp2Fo8= -----END CERTIFICATE----- """ intermediate_pem = """-----BEGIN CERTIFICATE----- MIIFtDCCBJygAwIBAgIQCIjNUl8ZJERNFKWCkd65UjANBgkqhkiG9w0BAQsFADBa MQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJl clRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTE2 MDUyMDEyNTMwM1oXDTI0MDUyMDEyNTMwM1owgYsxCzAJBgNVBAYTAlVTMRMwEQYD VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy b3NvZnQgQ29ycG9yYXRpb24xFTATBgNVBAsTDE1pY3Jvc29mdCBJVDEeMBwGA1UE AxMVTWljcm9zb2Z0IElUIFRMUyBDQSA1MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEAmt+BXDuPrul5lrmaeaeB8jnaVShGIwLFgmYHthXe/Zw6GpuRCdJm jwuJF/hxhyF/ONM/miUAtzXQq/gIejbzUFvfKykn3qTdJJL69MZwjTYqmvCA3jX6 HkKdCYGq1QcKFqXFWkJtQr4eQoK0VzCZW0Ur1I/TCgbGc5Ok4YPvxb8FJ6d4zbML 4J4iFvOY3KYU6MyU1yP50FCZu7ULEJXx3wLpj46dVpk82I/TWPtckn49e/hQSVr3 EHt3+OZKkEpVUt6UrXQJoGRXLM0HkJ8WrZXD0Qa68e9sBbUErKncGzGbDi0ZlQRP 3mbLrTVyrxmCCLIUOhZfsDyb240MsALWJh/oFXHE7/ljOUOM6cKSLqHCoDAlDpYn X56jK4LWEL08GR6mh/5VITpcQfwBmMwvkv9mOLS4ZpwPEmhLSqyGu16Y/56mnFNs MxGk0K5SR9eLj/GWrLkpmo8s8a1kGMMmuwBk3lBwwLvsxmuu06DvwPFcDfLMelna GDMvWRCtZxQsXyJDSkTh6N3g51UWTgnvA0wMSFBa8APfju9jyltnh0NALAa2Hw8+ U8BmP9cUFeYIYphIfoPlp7VdUS1ULWH9NF3Ut4DN0n3OsSQ785dsbBPeihfJivVI lUL3EpDjEBf2oQDFNiplkZ4F7EIuWriZG//UTrX6ZlXZg46/CCmN+gsCAwEAAaOC AUIwggE+MB0GA1UdDgQWBBQI/iWfdOqHBMK8u46oOF8zxtFsZTAfBgNVHSMEGDAW gBTlnVkwgkdYzKz6CFQ2hns6tQRN8DASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud DwEB/wQEAwIBhjAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUF BwMJMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln aWNlcnQuY29tMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 LmNvbS9PbW5pcm9vdDIwMjUuY3JsMD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsG AQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA0GCSqGSIb3DQEB CwUAA4IBAQA+8s8wpXq/HmrfOVgYKDzDne7ngcVL/Gf2vx9ON9re8K/uivkDe2Bn dMc72v8rSuv9VHUTi+XCgRK6UhIguimKOs1DJMzVFwX+nBY/c+BtQcB2PfKrSMVZ YmS6RE8KGII/Qeo/GDpY56AwV3X10WoxFLaUmWXatugB3uSr+7Xz5RkKGF+kAlfe tlwmb3P+Lgn1CEPED8ckf50oZ2Wh3FvwOv34cIXnpU8k3kI/HUQ7XYUGhR0eHNTZ TlHk/R4RFsyeANmXGpfjZceGNRtTdr4y0SxBSUujPpMMW3dXBzA8NYuM0WmiJ/pV 6KudEB7RF9+6bInTyVvXC5SIqdi0ldeO -----END CERTIFICATE----- """ return [X509(leaf_pem), X509(intermediate_pem)]
def from_pem(cls, pem_certificate): # type: (Text) -> X509Certificate """Create an X509Certificate object from a PEM-formatted certificate. """ x509 = X509(pem_certificate) return cls(x509)
def get_certificate_chain_verify_result(self): # type: () -> Tuple[int, str] verify_result = self._ssl.get_verify_result() verify_result_str = X509.verify_cert_error_string(verify_result) return verify_result, verify_result_str