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 完整操作流程(一张图说清楚)
下面这张图,把单设备吊销的完整流程串起来了。我建议你把它打印出来贴在工位上。
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。