4. 数字证书与PKI体系:X.509证书格式、CA链、证书吊销
讲到TLS握手,绕不开数字证书。你可能觉得证书就是个文件,配好就行。但真到排障时,很多问题都出在证书身上。我见过不少团队因为证书链不全,导致生产环境大面积中断。今天咱们就把这背后的PKI体系彻底捋清楚。
4.1 X.509证书格式——证书的“身份证”
X.509是国际标准,定义了数字证书的格式。目前用最多的是v3版本。它不像普通文件那样随便写几行字段,而是用ASN.1编码的。
我早期做安全开发时,第一次用openssl x509 -text命令看证书,被一大堆字段吓到了。其实核心就那么几个:
| 字段 | 含义 | 备注 |
|---|---|---|
| Version | 版本号(v1/v2/v3) | 现在基本都用v3 |
| Serial Number | 证书序列号(唯一) | CA分配,吊销时用 |
| Signature Algorithm | 签名算法 | 比如SHA256withRSA |
| Issuer | 颁发者(CA名称) | 谁签的 |
| Validity | 有效期(起止时间) | 别过期了 |
| Subject | 主体(证书持有者) | 就是你的域名/组织 |
| Subject Public Key Info | 公钥算法+公钥值 | TLS握手时用 |
| Extensions | 扩展项(v3才有) | 关键扩展:CA标志、密钥用法等 |
重点:Signature字段是CA用自己私钥对证书内容签名的结果。客户端验证证书时,会用CA公钥算一次,确认没被篡改。
咱们用命令看一下真实证书结构:
openssl x509 -in example.crt -text -noout
输出里有一个类似这样的片段:
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 0x12345678...
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, O=Example CA, CN=Example Root CA
Validity
Not Before: Jan 1 00:00:00 2024 GMT
Not After : Jan 1 00:00:00 2025 GMT
Subject: C=CN, O=Example Org, CN=www.example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
...
嗯,这里要注意:Basic Constraints 这个扩展非常重要。CA证书的CA标志为TRUE,终端用户证书为FALSE。如果乱配,客户端会认为它是非法CA,直接拒绝连接。我见过有人把终端证书的CA标志误设成TRUE,结果浏览器报错“证书链不完整”。
4.2 CA链——信任的传递
单独的证书没有意义,必须有一条完整的证书链。根CA自签名,然后签发中间CA,中间CA再签发终端证书。客户端验证时,要用信任库里的根证书去校验上一级签名,一级级往上推。
为什么要有中间CA?直接根CA签发终端证书不更简单吗?
说实话,这么做是为了隔离风险。根CA私钥如果泄露,整个体系就完了。所以一般把根CA离线冷存储,日常签发用中间CA。就算中间CA出事,吊销它就行,根CA还能继续用。我在给金融客户做PKI方案时,他们要求根CA的私钥必须放在硬件加密机里,物理隔离。
典型的CA链结构:
- 根CA证书(自签名,信任锚)
- 中间CA证书(由根CA签发,CA标志为TRUE)
- 终端证书(由中间CA签发,CA标志为FALSE)
服务器配置时,需要把中间CA和终端证书拼接在一起发过去,根证书不用发(客户端自己已预置)。很多新手把根证书也塞进去,或者顺序放反,导致验证失败。
小技巧:用 openssl verify -CAfile root.crt -untrusted intermediate.crt server.crt 可以快速验证链是否完整。我每次发布前都会跑一次这个命令,避免人工拼错。
4.3 证书吊销——CRL与OCSP
证书不是永久的。私钥泄露、域名变更、员工离职……都需要吊销证书,让客户端不再信任它。两种主流方式:CRL(证书吊销列表)和OCSP(在线证书状态协议)。
| 方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| CRL | CA定期发布一个列表,包含所有被吊销证书的序列号 | 实现简单,离线可查 | 列表会变大,有延迟 |
| OCSP | 客户端实时向OCSP响应器查询单个证书状态 | 实时性强,负载小 | 依赖网络,OCSP响应器可能宕机 |
实际部署中,OCSP更常用。但有个坑:OCSP必须响应快,否则客户端会超时。我经历过一次OCSP响应器性能不足,导致TLS握手变慢,用户抱怨页面加载卡顿。后来加了OCSP Stapling,让服务器自己缓存并推送状态,问题才解决。
注意:CRL和OCSP都不是实时的,有吊销延迟。所谓“实时吊销”其实靠缩短CRL有效期或OCSP缓存时间来实现。理论上私钥泄露后,攻击者仍可能用已吊销的证书短暂攻击。这一点在合规审计时要考虑。
查看CRL的方法:
openssl crl -in crl.pem -text -noout
OCSP请求示例(用openssl模拟):
openssl ocsp -issuer intermediate.crt -cert server.crt -url http://ocsp.example.com -text
4.4 知识结构图
下面这张图把PKI体系的核心概念串起来了。
核心回顾:证书格式是基础,CA链构建信任,吊销机制确保撤销能力。三者缺一不可。配置TLS时,记住这三步:检查证书格式是否完整(含扩展项)→ 确认链顺序是否正确 → 确保OCSP/CRL可达。曾经有个客户线上证书过期,就是因为CRL缓存没有及时刷新,导致客户端一直走旧查询路径。从那以后我养成了一个习惯:每次证书轮换,都把新的CRL分发点也验证一遍。
本章内容到此结束。理解这些,你就能在TLS证书相关的问题上游刃有余了。