You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用cryptography.x509签名证书时遇缺失必需扩展错误,求排查

问题解决:证书验证提示“Certificate is missing required extension”

核心问题分析

出现该错误主要有两个原因:

  • 服务器证书缺少**Extended Key Usage(扩展密钥用法)**扩展,TLS服务器证书必须明确标注用于服务器身份验证(serverAuth)
  • 验证逻辑未将自签CA证书加入受信任存储,误用公网根证书库导致CA不被信任

修改后的代码

证书生成部分(添加必要扩展)

def generate_sign_sret():
    from datetime import datetime, timedelta
    from cryptography import x509
    from cryptography.x509.oid import OID_SERVER_AUTH
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.backends import default_backend

    with open("csr.pem", "rb") as f:
        pem_req_data = f.read()
    server_csr = x509.load_pem_x509_csr(pem_req_data)
    with open("cert.pem", "rb") as f:
        ca_pem_req_data = f.read()
    ca_cert = x509.load_pem_x509_certificate(ca_pem_req_data)
    
    # 需提前加载CA私钥,示例:
    # with open("ca_private_key.pem", "rb") as f:
    #     key = serialization.load_pem_private_key(f.read(), password=None, backend=default_backend())

    # 签发服务器证书
    server_cert = (
        x509.CertificateBuilder()
        .subject_name(server_csr.subject)
        .issuer_name(ca_cert.subject)
        .public_key(server_csr.public_key())
        .serial_number(x509.random_serial_number())
        .not_valid_before(datetime.now() - timedelta(days=1))
        .not_valid_after(datetime.now() + timedelta(days=365))
        # 主机名SAN扩展
        .add_extension(
            x509.SubjectAlternativeName([x509.DNSName("cryptography.io")]),
            critical=False,
        )
        # 基础约束:明确不是CA证书
        .add_extension(
            x509.BasicConstraints(ca=False, path_length=None),
            critical=True,
        )
        # 密钥用法:适配服务器证书需求
        .add_extension(
            x509.KeyUsage(
                digital_signature=True,
                key_encipherment=True,
                data_encipherment=True,
                key_agreement=True,
                key_cert_sign=False,
                crl_sign=False,
                content_commitment=True,
                encipher_only=False,
                decipher_only=False
            ),
            critical=True,
        )
        # 新增:扩展密钥用法,指定服务器身份验证用途
        .add_extension(
            x509.ExtendedKeyUsage([OID_SERVER_AUTH]),
            critical=False,
        )
        # 使用CA私钥签发
        .sign(key, hashes.SHA256(), default_backend())
    )
    server_cert_bytes = server_cert.public_bytes(encoding=serialization.Encoding.PEM)
    with open("server_cert.pem", "wb") as f:
        f.write(server_cert_bytes)

证书验证部分(修正信任存储)

def verifyCert():
    from cryptography import x509
    from cryptography.hazmat.backends import default_backend
    from cryptography.x509.verification import Store, PolicyBuilder, VerificationError

    with open("cert.pem", "rb") as f:
        ca_pem_req_data = f.read()
    ca_cert = x509.load_pem_x509_certificate(ca_pem_req_data, default_backend())

    with open("server_cert.pem", "rb") as f:
        server_pem_req_data = f.read()
    server_cert = x509.load_pem_x509_certificate(server_pem_req_data, default_backend())

    # 创建仅包含自签CA的受信任存储
    store = Store([ca_cert])
    # 构建服务器证书验证策略
    trust_builder = PolicyBuilder().store(store)
    verifier = trust_builder.build_server_verifier(x509.DNSName("cryptography.io"))
    try:
        # 传入证书链:服务器证书在前,CA证书在后
        verifier.verify(server_cert, [ca_cert])
        print("Server certificate is valid.")
    except VerificationError as e:
        print("Server certificate validation failed:", e)
    except Exception as e:
        print("Unexpected error during validation:", e)

关键修改说明

  1. 添加Extended Key Usage扩展:这是TLS服务器证书的强制要求,明确声明证书用于服务器身份验证,直接解决“缺少必要扩展”的错误。
  2. 修正信任存储:将自签CA证书加入受信任列表,避免使用公网根证书库(自签CA不在公可信列表中,会导致信任链验证失败)。
  3. 优化密钥用法参数:关闭key_cert_sign和crl_sign权限,符合服务器证书不能签发其他证书的特性。

内容的提问来源于stack exchange,提问作者Cheng Cui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 17:04:56