TLS 证书与 PKI:X.509 证书格式、证书链验证、CA 信任体系、证书吊销机制
这一章我们聊点实在的——TLS 证书和 PKI。说实话,很多人觉得证书就是个加密文件,装上就行。但我在实际项目里踩过不少坑,证书链断掉、中间 CA 没装、吊销检查超时……每一个都能让你的 TLS 握手原地爆炸。所以这次我把自己的经验揉进去,带你把这几个最核心的概念啃透。
X.509 证书格式:到底长什么样?
先来看证书本身。X.509 是国际标准,现在用的基本都是 v3 版本。我刚开始接触时,以为证书就是个公钥加个签名——太天真了。它其实是一堆字段的集合,每个字段都有具体用途。
一张 TLS 服务器证书里,至少包含下面这些关键信息:
| 字段 | 含义 | 典型值(示例) |
|---|---|---|
| 版本号 | X.509 版本,目前多为 v3 | 2(表示 v3) |
| 序列号 | CA 颁发的唯一整数 | 0x01A2B3… |
| 签名算法 | 签发证书用的算法 | sha256WithRSAEncryption |
| 颁发者(Issuer) | 签发该证书的 CA 名称 | C=CN, O=MyCA, CN=Root CA |
| 有效期 | 起止时间 | Not Before / Not After |
| 主体(Subject) | 证书持有者名称 | C=CN, O=Example, CN=www.example.com |
| 公钥信息 | 算法 + 公钥值 | RSA 2048 bits |
| 扩展域 | v3 扩展,如 SAN、密钥用法等 | DNS: example.com |
| 签名值 | CA 对以上字段的签名 | 256 字节的 RSA 签名 |
Subject 和 SAN(主题备用名称)。很多证书链问题其实是 SAN 不匹配导致的,尤其是浏览器访问。我在公司内部平台排过不少这种低级故障。
CA 信任体系与证书链:为什么需要中间人?
直接拿根 CA 签服务器证书行不行?技术上可以,但没人这么干。你想想,如果根密钥泄露,整个信任体系就崩了。所以现实中用的是分层结构——CA 信任体系。
这个结构像一棵树:根 CA(自签名)→ 中间 CA(二级、三级)→ 最终实体证书(服务器/客户端)。
为什么要这么麻烦?
- 安全隔离:根 CA 离线存储,日常签发用中间 CA。即使中间 CA 出问题,根 CA 还能撤销它。
- 组织灵活:不同部门可以用不同的中间 CA,权限分开。
- 兼容性:浏览器只预置了少数根 CA,中间 CA 可以自己签发,节省成本。
证书链就是这一串从根到叶的证书序列。验证时,客户端需要拿到完整的链——不包括根(客户端本地已经有根),但必须包含所有中间 CA。我在项目里见过运维只配了服务器证书,没配中间 CA,结果安卓设备死活连不上,因为安卓不自动补链。
ssl_certificate 指向服务器证书,忘了配 ssl_trusted_certificate 链文件。结果 Chrome 通过(它自己去下载中间证书),但老旧客户端一直报错。后来我统一把完整链(不含根)串到一个 PEM 文件里,再没出过问题。
证书链验证过程:一步一步拆给你看
验证不是简单比对签名就完事。客户端拿到服务器证书 + 中间证书后,会做下面这几步:
- 叶子证书验证:检查有效期、用途(如 TLS Web Server Authentication)、域名 SAN 匹配。
- 构建链:从叶子证书开始,用它的
Issuer字段找到上一级证书(中间 CA),直到遇到一个客户端信任的根 CA。 - 签名验证:用上级证书的公钥验证下级证书的签名值,一级一级往上。
- 吊销检查:验证链上的每一张证书是否被吊销(见下一节)。
- 信任锚检查:最终到达的证书必须出现在客户端的信任存储里(即浏览器/系统的根证书列表)。
我遇到过最诡异的情况:中间 CA 证书的有效期比叶子证书短,导致叶子证书还没过期,中间 CA 先过期了——连接直接断开。所以签发证书时,中间 CA 的有效期一定要大于所有下级证书。
下面这张图概括了 X.509 证书与 PKI 信任体系的完整结构:
证书吊销机制:CRL 与 OCSP
证书没到期就不能撤销吗?当然可以。私钥泄露、员工离职、域名变更——这些情况都需要立即吊销证书,不能等它自然过期。那客户端怎么知道一张证书被吊销了?两个主流方式:CRL 和 OCSP。
CRL(证书撤销列表),说白了就是一张黑名单。CA 定期发布一个列表,包含所有被吊销证书的序列号和吊销时间。客户端下载这个列表,然后比对目标证书的序列号是否在里面。
- 优点:简单、离线可用。
- 缺点:列表会越来越大;更新有延迟(CRL 一般几天更新一次);每次都要下载整个列表,流量大。
OCSP(在线证书状态协议),则是实时查询。客户端向 OCSP 响应器(由 CA 维护)发送请求“这张证书现在有效吗?”,服务器返回“good”、“revoked”或“unknown”。
- 优点:实时、精确、列表小。
- 缺点:依赖网络;OCSP 响应器可能宕机或慢;客户端必须支持 OCSP(现在都支持)。
现实中还有一个变体叫 OCSP Stapling——服务器自己去 OCSP 响应器拿一个带时间戳的响应结果,然后在 TLS 握手时“钉”给客户端。这样客户端不用额外请求,减少延迟和隐私泄露(否则 CA 知道哪个用户访问了哪个网站)。
| 特性 | CRL | OCSP | OCSP Stapling |
|---|---|---|---|
| 实时性 | 低(周期更新) | 高(实时查询) | 较高(缓存时效) |
| 网络依赖 | 下载列表(可缓存) | 每次查询 | 服务器主动做 |
| 隐私泄露 | 无(下载全部列表) | 有(CA 知道客户端 IP) | 无(服务器代为查询) |
| 部署复杂度 | 低 | 中 | 较高(需要服务器支持) |
Authority Information Access 指向了内网地址,导致公网客户端查不到状态,全部报错。那真是个糟糕的周五下午。
好了,关于证书格式、信任链、验证流程和吊销机制,核心内容就这些。第三章讲的东西你在实际排错中会反复用到——从抓包看到证书链不全,到 OCSP 响应超时,再到根证书过期……记住了这些基础,后面谈 TLS 1.3 握手、证书透明度时就不会慌。