Skip to content
ecdsa.com
Python 3.13+ ssl modulePython cryptography

Error message

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: CA cert does not include key usage extension

Appears after upgrading to Python 3.13 or later; earlier versions do not set the strict flag. Followed by a source location such as "(_ssl.c:1082)". openssl verify -x509_strict reports the same check as "error 92 at 1 depth lookup: CA cert does not include key usage extension".

Python 3.13+ ssl module — VERIFY_X509_STRICT in create_default_context(), X509_V_ERR_CA_CERT_MISSING_KEY_USAGE (92)

What it means

Since Python 3.13, ssl.create_default_context() enables OpenSSL's strict X.509 checks (VERIFY_X509_STRICT). One of them requires every CA certificate to carry a keyUsage extension allowing certificate signing, as RFC 5280 demands. Your CA certificate has no keyUsage, so a chain that worked on Python 3.12 is now rejected even though the CA is explicitly trusted.

Why it happens

How to fix it

  1. 1.

    Confirm which extension is missing

    Print the CA's basicConstraints and keyUsage, and run openssl verify -x509_strict to see every strict-mode failure at once.

    bash
    openssl x509 -in ca.pem -noout -ext basicConstraints,keyUsage
    # Same strict checks as Python 3.13+, without Python:
    openssl verify -x509_strict -CAfile ca.pem server.pem
  2. 2.

    Reissue the CA certificate with keyUsage

    Re-sign the CA with keyUsage = critical, keyCertSign, cRLSign (and basicConstraints critical). If you keep the same key and subject, certificates it already issued still chain to the new CA certificate; distribute the new CA file to clients.

    bash
    # A CA certificate with the extensions RFC 5280 requires
    openssl req -x509 -new -key ca.key -days 3650 -subj "/CN=Example Private CA" \
      -addext "basicConstraints=critical,CA:TRUE" \
      -addext "keyUsage=critical,keyCertSign,cRLSign" \
      -out ca.pem
    # Reusing the old key and subject keeps already issued certificates verifiable.
  3. 3.

    Temporary workaround: clear VERIFY_X509_STRICT for this context

    Clearing the flag restores the Python 3.12 behaviour for one context. It is not the same as disabling verification, but it does accept certificates that violate RFC 5280; remove it once the CA is fixed.

    python
    # Temporary workaround while the CA is reissued: the chain, dates and host name
    # are still verified, only the RFC 5280 profile checks are relaxed.
    import ssl
    ctx = ssl.create_default_context(cafile="ca.pem")
    ctx.verify_flags &= ~ssl.VERIFY_X509_STRICT

Related errors

Browse the full signature error database