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

如何使用x509.CertificateBuilder为证书添加信任链?

如何将CA证书加入用cryptography.x509.CertificateBuilder生成的证书链中?

我正在使用cryptography.x509.CertificateBuilder生成证书,代码如下:

from pathlib import Path
from cryptography import x509
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import Encoding

private_key: rsa.RSAPrivateKey

ca_cert: x509.Certificate
ca_cert_private_key: rsa.RSAPrivateKey

cert = (
    x509.CertificateBuilder()
    .subject_name(x509.Name.from_rfc4514_string(f"CN={workstation_name}"))
    .issuer_name(ca_cert.subject)
    .public_key(private_key.public_key())
    .serial_number(x509.random_serial_number())
    .not_valid_before(today)
    .not_valid_after(today + timedelta(days=60))
    .add_extension(subject_alt_name, critical=False)
    .sign(ca_cert_private_key)
)
Path("workstation.crt").write_bytes(cert.public_bytes(Encoding.PEM))

现在我想把ca_cert添加到生成的证书的证书链中。比如Stack Overflow的证书链包含3个证书:

$ openssl s_client -connect stackoverflow.com:443
CONNECTED(00000003)
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = *.stackexchange.com
verify return:1
---
Certificate chain
 0 s:CN = *.stackexchange.com
   i:C = US, O = Let's Encrypt, CN = R3
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Dec 18 14:08:17 2022 GMT; NotAfter: Mar 18 14:08:16 2023 GMT
 1 s:C = US, O = Let's Encrypt, CN = R3
   i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Sep  4 00:00:00 2020 GMT; NotAfter: Sep 15 16:00:00 2025 GMT
 2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
   i:O = Digital Signature Trust Co., CN = DST Root CA X3
   a:PKEY: rsaEncryption, 4096 (bit); sigalg: RSA-SHA256
   v:NotBefore: Jan 20 19:14:03 2021 GMT; NotAfter: Sep 30 18:14:03 2024 GMT
---

但我生成的证书链里只有1个证书:

$ openssl s_client -connect localhost:443
CONNECTED(00000003)
Can't use SSL_get_servername
depth=1 CN = [Redacted CA Cert Name]
verify return:1
depth=0 CN = [Redacted Workstation Name]
verify return:1
---
Certificate chain
 0 s:CN = [Redacted Workstation Name]
   i:CN = [Redacted CA Cert Name]
---

请问怎么把ca_cert作为第2个证书加入到证书链中?


解决方法

证书链本质是将多个PEM格式的证书按顺序拼接成一个文件,核心规则是:终端实体证书(你的工作站证书)放在最前面,之后依次添加签发它的中间CA证书、根CA证书(如果需要)。

只需要修改代码,把工作站证书和CA证书的PEM内容合并后写入同一个文件即可:

from pathlib import Path
from cryptography import x509
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import Encoding
from datetime import timedelta

private_key: rsa.RSAPrivateKey

ca_cert: x509.Certificate
ca_cert_private_key: rsa.RSAPrivateKey
workstation_name = "你的工作站名称"
today = x509.utcnow()
subject_alt_name = x509.SubjectAlternativeName([x509.DNSName("localhost")]) # 示例SAN,根据实际情况调整

# 生成工作站证书
cert = (
    x509.CertificateBuilder()
    .subject_name(x509.Name.from_rfc4514_string(f"CN={workstation_name}"))
    .issuer_name(ca_cert.subject)
    .public_key(private_key.public_key())
    .serial_number(x509.random_serial_number())
    .not_valid_before(today)
    .not_valid_after(today + timedelta(days=60))
    .add_extension(subject_alt_name, critical=False)
    .sign(ca_cert_private_key)
)

# 拼接证书链:工作站证书 + CA证书(注意中间加换行分隔)
cert_chain_pem = cert.public_bytes(Encoding.PEM) + b"\n" + ca_cert.public_bytes(Encoding.PEM)

# 写入带证书链的文件
Path("workstation_chain.crt").write_bytes(cert_chain_pem)

验证效果

修改后,用openssl s_client连接服务时,就能看到证书链包含两个证书:

$ openssl s_client -connect localhost:443
CONNECTED(00000003)
# ... 省略其他输出 ...
---
Certificate chain
 0 s:CN = [你的工作站名称]
   i:CN = [CA证书名称]
 1 s:CN = [CA证书名称]
   i:CN = [CA的签发者名称]
---

额外说明

  • 如果你的CA证书还有上层根CA,可以继续把根CA的PEM内容追加到文件末尾,形成完整的信任链。
  • 务必保证证书顺序正确:终端证书在前,后续CA证书按"子CA在前、父CA在后"排列,否则客户端无法正常验证信任关系。

内容的提问来源于Stack Exchange,提问作者Gary van der Merwe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:25:16