CRL 基础知识:先搞懂证书吊销这件事

你想想看,一台服务器用的证书明明还没到期,为什么突然就不能用了?

原因很简单——证书被吊销了。就像信用卡丢了,你得挂失一样。证书密钥泄露、证书颁发错误、域名所有权变更……这些场景下,CA(证书颁发机构)必须把证书提前作废。

今天我们就从最基础的东西聊起,什么叫 CRL,它到底长什么样,怎么用。

为什么需要 CRL?

X.509 证书本身是有有效期的,通常 1 年或 2 年。但在没到期之前,有些特殊情况必须让证书提前失效:

  • 私钥泄露或怀疑泄露
  • 证书信息有误(域名、组织名等)
  • 员工离职、域名废弃
  • CA 自身被入侵

CA 必须把这类证书“拉黑”,让客户端在验证时拒绝放行。这种方式就是证书吊销。而 CRL(Certificate Revocation List,证书吊销列表) 就是 CA 定期发布的一个“黑名单”文件。

我个人习惯把 CRL 理解成一张电子公告板。CA 在公告板上写着:以下证书已失效,请大家别信了。客户端每次做证书校验时,都得来扫一眼这块公告板。

CRL 的定义和作用

严格按照 RFC 5280 的说法,CRL 是一个由 CA 签名的时间戳列表,包含了所有已吊销但未到期的证书序列号。说白了,它就是一张经过数字签名的“作废清单”。

它的核心作用有两条:

  1. 告知状态:告诉所有客户端,哪些证书已经不可信。
  2. 形成证据:CRL 由 CA 签名,不可抵赖,可以用于审计。

我在项目中遇到过好几次,运维同学以为证书到期前就是安全的,结果私钥泄露导致中间人攻击,就是因为没有及时刷新 CRL,系统还在信任已吊销的证书。

CRL 长什么样?

RFC 5280 规定的 CRL 使用 ASN.1 语法编码,实际存储一般是 DER 或 PEM 格式。你用 OpenSSL 命令可以把它解析出来看。

提取 CRL 并查看内容:

# 下载 CRL 文件
curl -O http://crl.example.com/ca.crl

# 查看 CRL 内容(DER 格式)
openssl crl -in ca.crl -inform DER -text -noout

# 如果是 PEM 格式
openssl crl -in ca.crl -inform PEM -text -noout

解析出来的内容大概长这样:

Certificate Revocation List (CRL):
        Version 2 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: /C=CN/ST=Beijing/L=Haidian/O=Example CA
        Last Update: Jun  1 10:00:00 2025 GMT
        Next Update: Jun  8 10:00:00 2025 GMT
        CRL extensions:
            X509v3 Authority Key Identifier: ...
            X509v3 CRL Number: 12345
Revoked Certificates:
    Serial Number: 0xABCDEF1234567890
        Revocation Date: May 28 14:30:00 2025 GMT
        CRL Reason Code: keyCompromise
    Serial Number: 0x1122334455667788
        Revocation Date: May 29 09:00:00 2025 GMT
        CRL Reason Code: affiliationChanged

这里最关键是几个字段:

字段 含义 运维关注点
Issuer 签发该 CRL 的 CA 名称 必须与要验证的证书的签发者一致
Last Update 本次 CRL 发布时间 客户端拿到的是否最新版
Next Update 下次 CRL 更新时间 过了这个时间,CRL 失效,必须重新拉取
Serial Number 被吊销证书的序列号 比对客户端证书的序列号是否命中
Revocation Date 吊销发生的时间戳 用于判定吊销发生的先后顺序
CRL Reason Code 吊销原因 常见:keyCompromise、caCompromise、superseded、cessationOfOperation
重要提醒:CRL 本身也是由 CA 的私钥签名的。你把 CRL 下载下来后,客户端会用 CA 的证书公钥去验证 CRL 文件是否被篡改。如果验证失败,整个吊销列表都不能信。

CRL 的分发与获取

CA 不会主动把 CRL 推送给你,需要你自己去拉。证书里通常会内嵌一个 CRL Distribution Point(CRL 分发点) 的 URL,告诉你上哪儿下载。

查看证书中的 CRL 分发点:

openssl x509 -in server.crt -text -noout | grep -A 4 "CRL Distribution Points"

输出类似这样:

X509v3 CRL Distribution Points:
    Full Name:
        URI:http://crl.example.com/ca.crl

嗯,这里要注意,很多企业 CA 会有多个分发点,比如同时提供 HTTP 和 LDAP 两种方式,甚至还有 OCSP 替代方案。

CRL 与 OCSP 的区别

CRL 有一个天生的短板——它是个静态列表。CA 每隔一段时间(比如 7 天)才发布一次新版本。客户端拉到的 CRL,有效期覆盖整整一段时间。如果某个证书刚被吊销,CRL 是来不及同步的。

为了解决这个问题,RFC 2560 定义了 OCSP(在线证书状态协议)。OCSP 可以实时查询单个证书的状态,不需要下载整个列表。

对比维度 CRL OCSP
查询方式 下载整个列表,本地匹配 发送请求,查询单个证书
实时性 延迟一次发布周期(几十小时到几天) 实时查询,毫秒级响应
网络开销 列表可能很大(几 MB 到几十 MB) 请求体积小,约几百字节
离线能力 支持,缓存 CRL 即可 必须联网
部署复杂度 低,架个静态文件服务就能跑 需要 OCSP 响应器,配置复杂

现实中,大多数浏览器和服务器其实是两者都支持。但我个人建议在生产环境里优先用 OCSP,实时性好太多。CRL 可以作为兜底方案——当 OCSP 服务挂了,客户端还能退回来查 CRL。

一张图看清 CRL 在 PKI 里的位置

CRL 在 PKI 证书验证中的位置 CA 根证书 信任锚点 中间 CA 证书 签发最终证书 Web 服务器证书 subject.example.com CRL 分发点 http://crl.example.com/ca.crl CRL 缓存文件 有效期至:Next Update 客户端校验 比对序列号是否命中 证书内嵌 CRL 分发点 URL 关闭警告 CRL 未及时刷新 → 信任已吊销证书 → 安全事件

CRL 分发失败会怎样?

讲到这里,很多人会问:如果 CRL 拉不到,客户端会拒绝连接吗?

不一定。这取决于客户端的策略。有些严格的策略(比如金融行业)规定:如果无法获取 CRL 或 OCSP 响应,直接拒绝信任,这叫“hard-fail”。但大部分浏览器默认是“soft-fail”,即拉不到 CRL 就忽略,继续信任证书——说白了,拉不到就当没吊销。

我曾经碰到过一个案例:某公司的内部 CA 突然停机,CRL 分发点挂了两天。所有客户端由于 soft-fail 策略,继续信任了一个已被吊销的证书。结果攻击者利用这个证书在内网做了中间人攻击,截获了所有 LDAP 流量……那真是血泪教训。

所以我建议企业环境里,一定要配置硬失败策略,让 CRL 抓取失败时直接拒绝连接。虽然会牺牲一些可用性,但安全性是实打实的。

小结一下

  • CRL 是 CA 签名的已吊销证书列表,用于客户端校验证书状态。
  • 核心字段包括序列号、吊销时间、吊销原因、发布有效期。
  • CRL 分发点通常内嵌在证书扩展里,支持 HTTP 或 LDAP 方式下载。
  • CRL 有延迟问题,实时场景推荐搭配 OCSP 使用。
  • CRL 获取失败时的行为策略(hard-fail vs soft-fail)直接决定系统安全水位。