跳到主要内容
ecdsa.com
Python 3.13+ ssl modulePython cryptography 库

错误信息

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Basic Constraints of CA cert not marked critical

只有启用了严格检查的客户端才会打印这条消息:默认启用严格检查的 Python 3.13 及更高版本,以及 openssl verify -x509_strict。Python 还会附加源代码位置,例如“(_ssl.c:1082)”。

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

含义

Python 3.13+ 使用 OpenSSL 的严格 X.509 模式进行验证,该模式强制执行 RFC 5280 的规定:CA 证书的 basicConstraints 扩展必须标记为关键(critical)。你的证书链中的 CA 带有 basicConstraints CA:TRUE,但没有 critical 标志,因此即使这个 CA 受信任,OpenSSL 也会拒绝这条证书链。

原因

修复方法

  1. 1.

    找出不合规的证书

    输出证书链中每张 CA 证书的 basicConstraints;没有“critical”的那张必须重新签发。openssl verify -x509_strict 会显示所有严格模式下的问题。

    bash
    openssl x509 -in ca.pem -noout -ext basicConstraints
    # X509v3 Basic Constraints:            <- no "critical" here is the problem
    #     CA:TRUE
    openssl verify -x509_strict -CAfile ca.pem server.pem
  2. 2.

    重新签发 CA,并把 basicConstraints 标记为关键扩展

    重新签名 CA 证书,设置 basicConstraints = critical, CA:TRUE,并添加 keyUsage 扩展。保持密钥和主体不变,现有证书就仍能通过它验证。

    bash
    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
  3. 3.

    临时规避方案:清除 VERIFY_X509_STRICT

    在修复 CA 期间,为单个上下文恢复 3.13 之前的行为。证书链、有效期和主机名的验证仍然保持开启。

    python
    # Temporary workaround until the CA is reissued (chain, dates and name are still checked)
    import ssl
    ctx = ssl.create_default_context(cafile="ca.pem")
    ctx.verify_flags &= ~ssl.VERIFY_X509_STRICT

相关错误

浏览完整的签名错误库