3、单设备吊销实操:使用OpenSSL吊销单个证书、生成CRL、验证吊销结果

好,咱们进入真正的动手环节了。

前面两章讲了吊销的原理和规划,说白了都是纸上谈兵。这一章,咱们得真刀真枪地干一把——用 OpenSSL 把一张证书吊销掉,生成 CRL,再验证一下吊销到底生效了没有。

我个人习惯,学任何技术都先跑通一个最小闭环。你想想看,如果连单设备吊销都搞不定,后面批量操作更是无从谈起。所以这一章虽然基础,但它是后面所有高级操作的基石。

本章核心目标:掌握 OpenSSL 吊销单张证书的完整命令链,理解 CRL 生成机制,并能独立验证吊销结果。

3.1 吊销前的准备工作

在动手之前,你得确保手头有这几样东西。我在项目中遇到过好几次,有人急匆匆跑来说“证书吊销不了”,结果一看,连 index.txt 都没创建。

准备项 说明 检查命令
CA 私钥 用于签署 CRL,必须保护好 ls -l ca.key
CA 证书 CRL 的签发者身份 openssl x509 -in ca.crt -text -noout | head -5
index.txt 证书数据库,记录所有已签发证书状态 cat index.txt
serial 当前序列号文件 cat serial
crlnumber CRL 序列号文件(首次需手动创建) echo 01 > crlnumber

注意:crlnumber 文件很容易被忽略。我第一次做 CRL 轮换时,就因为少了这个文件,OpenSSL 报了个莫名其妙的错误,排查了半天。建议你提前创建好,内容写 01 就行。

3.2 吊销单张证书:openssl ca -revoke

吊销命令其实就一行。但这一行背后,OpenSSL 做了不少事。

openssl ca -config openssl.cnf \
  -revoke device_cert.pem \
  -keyfile ca.key \
  -cert ca.crt

执行之后,发生了什么?

  • OpenSSL 读取 index.txt,找到与 device_cert.pem 匹配的记录
  • 将该记录的状态从 V(有效)改为 R(已吊销)
  • 记录吊销时间(默认是当前时间)
  • 你可以通过 -crl_reason 参数指定吊销原因

来看一下 index.txt 的变化。吊销前,记录大概是这样的:

V	240912120000Z		ABCD1234	unknown	/CN=device1

吊销后,变成了:

R	240912120000Z	240915080000Z	ABCD1234	unknown	/CN=device1

看到了吗?多了第二个时间戳,那就是吊销时间。状态也从 V 变成了 R。

小技巧:吊销原因我常用这几个:unspecified(未指定)、keyCompromise(密钥泄露)、superseded(被替代)。如果是设备报废,我习惯用 superseded;如果是安全事件,必须用 keyCompromise。这个选择会影响审计时的判断,别随便填。

3.3 生成 CRL:openssl ca -gencrl

吊销完证书,index.txt 里已经标记了。但客户端怎么知道这张证书被吊销了?

答案就是 CRL。你得把 index.txt 里的吊销记录,打包成一个标准的 CRL 文件,分发下去。

openssl ca -config openssl.cnf \
  -gencrl \
  -keyfile ca.key \
  -cert ca.crt \
  -out ca.crl

这条命令会读取 index.txt 中所有状态为 R 的记录,生成一个 DER 或 PEM 格式的 CRL。

你可以用这条命令查看 CRL 的内容:

openssl crl -in ca.crl -text -noout

输出里你会看到:

  • 签发者:就是你的 CA 证书的 Subject
  • 本次更新时间:生成 CRL 的时间
  • 下次更新时间:CRL 的有效期(默认 30 天,可在 openssl.cnf 中修改)
  • 已吊销证书列表:每个吊销的序列号、吊销时间、吊销原因

关键点:CRL 不是实时更新的。客户端拿到 CRL 后,会缓存到 nextUpdate 时间。所以如果你紧急吊销了一张证书,必须立即重新生成 CRL 并推送到客户端,否则客户端可能还在用旧的 CRL,认为那张证书是有效的。

3.4 验证吊销结果

CRL 生成了,怎么确认吊销真的生效了?

我一般做三步验证,缺一不可。

3.4.1 验证 CRL 本身是否合法

openssl crl -in ca.crl -CAfile ca.crt -noout -verify

如果输出 verify OK,说明 CRL 的签名是合法的,确实是你的 CA 签发的。

3.4.2 验证证书是否在 CRL 中

openssl crl -in ca.crl -text -noout | grep -A 1 "Serial Number"

或者更精确一点,直接查序列号:

openssl x509 -in device_cert.pem -noout -serial
openssl crl -in ca.crl -text -noout | grep <序列号>

如果找到了,说明吊销已记录。

3.4.3 模拟客户端验证(最推荐)

这一步最贴近真实场景。用 OpenSSL 模拟一个客户端,验证证书链时带上 CRL:

openssl verify -CAfile ca.crt -CRLfile ca.crl device_cert.pem

如果证书已被吊销,你会看到:

error 23 at 0 depth lookup: certificate revoked
device_cert.pem: verification failed

如果证书有效,输出是:

device_cert.pem: OK

我曾经踩过的坑:有一次我吊销了证书,也生成了 CRL,但 openssl verify 始终报 OK。查了半天,发现是 OpenSSL 版本问题——老版本默认不检查 CRL,需要加 -crl_check 参数。所以建议你养成习惯,验证时显式加上 -CRLfile 和 -crl_check。

3.5 完整操作流程(一张图说清楚)

下面这张图,把单设备吊销的完整流程串起来了。我建议你把它打印出来贴在工位上。

单设备吊销完整流程 单设备吊销完整流程 1. 准备工作 2. 吊销证书 3. 生成CRL 4. 验证CRL合法性 5. 验证证书吊销状态 6. 完成 关键命令 openssl ca -revoke openssl ca -gencrl openssl verify -CRLfile 常见吊销原因 • unspecified • keyCompromise • superseded

3.6 常见问题与避坑

最后,分享几个我实际项目中遇到的坑,你遇到了可以少走弯路。

问题 原因 解决方法
吊销时报错 unable to load certificate 证书文件路径不对或格式不对 用 openssl x509 -in 先确认证书能正常读取
生成 CRL 时报错 error:0D07209B crlnumber 文件缺失或内容格式错误 检查 crlnumber 是否存在,内容应为十六进制数字
验证时证书显示 OK 但实际已吊销 OpenSSL 版本太老,或未加 -crl_check 参数 升级 OpenSSL 或显式添加 -crl_check
CRL 中找不到刚吊销的证书 index.txt 中证书状态未更新,或 CRL 生成时未读取最新 index 检查 index.txt 状态是否为 R,重新执行 -gencrl

我的习惯:每次吊销完,我都会把 CRL 生成和验证写成一个小脚本,一键执行。这样既不会漏步骤,也方便后面批量操作时复用。你可以参考这个思路,把本章的命令串成一个 revoke_and_verify.sh。