3、OpenSSL生成CRL:命令行实战与签名验证

好,咱们进入实操环节。前面两章把CRL的理论和数据结构讲清楚了,这一章我带你直接用OpenSSL命令行把CRL生成出来、看明白、再验一遍签名。说白了,就是让你亲手摸到CRL长什么样。

我个人习惯在测试环境里先跑通一遍,再上生产。你想想看,万一生产上把CA私钥路径写错了,吊销列表发出去没人认,那可就尴尬了。嗯,咱们先从最基础的开始。

3.1 准备工作:你得有个CA

生成CRL之前,你手里必须有一个CA证书和对应的私钥。如果你还没有,可以用下面这条命令快速创建一个测试用的自签名CA:

# 生成CA私钥
openssl genrsa -out ca-key.pem 2048

# 生成自签名CA证书(有效期10年)
openssl req -x509 -new -nodes \
  -key ca-key.pem \
  -days 3650 \
  -out ca-cert.pem \
  -subj "/CN=Test CA/O=MyOrg/C=CN"
小提示:生产环境千万别用2048位以下的密钥,也别把有效期设这么长。我这里只是为了演示方便。

3.2 生成第一份CRL

有了CA,我们就可以生成CRL了。OpenSSL生成CRL的核心命令是 openssl ca -gencrl。看下面这个例子:

openssl ca -gencrl \
  -config /etc/pki/tls/openssl.cnf \
  -keyfile ca-key.pem \
  -cert ca-cert.pem \
  -out crl.pem

这条命令执行后,你会得到一个PEM格式的CRL文件。我刚开始用的时候,经常忘记指定 -config 参数,结果OpenSSL报错说找不到默认配置。嗯,这里要注意,-config 指向的配置文件里必须包含CA相关的路径设置。

如果你想指定CRL的有效期,可以用 -crldays 或 -crlhours 参数:

# 设置CRL有效期为30天
openssl ca -gencrl \
  -config /etc/pki/tls/openssl.cnf \
  -keyfile ca-key.pem \
  -cert ca-cert.pem \
  -crldays 30 \
  -out crl-30days.pem
避坑指南:我曾经在生产上遇到过一个问题——CRL的有效期设得太长(比如365天),结果中间有证书被吊销了,但CRL一直没更新,客户端拿着过期的吊销列表去验证,导致已吊销的证书被当成有效。后来我改成每7天生成一次,有效期设14天,留出缓冲时间。

3.3 查看CRL内容

生成完CRL,你得看看里面到底写了什么。用 openssl crl 命令可以查看:

# 查看CRL的文本内容
openssl crl -in crl.pem -text -noout

输出结果大致长这样:

Certificate Revocation List (CRL):
        Version 2 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: /CN=Test CA/O=MyOrg/C=CN
        Last Update: Apr  1 12:00:00 2025 GMT
        Next Update: May  1 12:00:00 2025 GMT
        CRL extensions:
            X509v3 Authority Key Identifier:
                keyid:AB:CD:EF:...
            X509v3 CRL Number:
                1
Revoked Certificates:
    Serial Number: 1234
        Revocation Date: Mar 15 10:30:00 2025 GMT
    Serial Number: 5678
        Revocation Date: Mar 20 14:00:00 2025 GMT

我来帮你拆解一下这些字段:

字段 含义 我的经验
Version CRL版本,目前基本都是v2 v1已经很少见了,别用
Signature Algorithm 签名算法,必须和CA证书一致 我建议用sha256WithRSAEncryption
Issuer 签发者DN,必须和CA证书的Subject一致 这里不一致会导致验证失败
Last Update / Next Update CRL的生效时间和过期时间 Next Update是客户端检查的关键
CRL Number CRL的序列号,每次更新递增 客户端可以用它判断CRL是否最新
Revoked Certificates 被吊销的证书序列号列表 每个条目都有吊销时间
重点:CRL的 Next Update 字段是客户端判断CRL是否过期的依据。如果客户端发现当前时间超过了 Next Update,它会认为CRL已失效,通常会拒绝所有该CA签发的证书。所以,一定要保证CRL的更新频率快于它的有效期。

3.4 验证CRL签名

CRL是CA签发的,所以它必须能被CA证书的公钥验证通过。验证命令很简单:

# 验证CRL签名
openssl crl -in crl.pem -CAfile ca-cert.pem -noout

如果签名验证通过,命令不会有任何输出(静默成功)。如果验证失败,你会看到类似这样的错误:

verify error:num=7:error:7FFF:CRL signature failure

为什么会失败?我遇到过几种情况:

  • CA证书不匹配:你用的CA证书和签发CRL的CA不是同一个。检查Issuer字段是否一致。
  • CRL被篡改:有人手动修改了CRL文件。签名会直接报错。
  • 算法不匹配:CA证书的签名算法和CRL的签名算法不一致。比如CA用sha256,CRL用sha1。
调试技巧:如果你怀疑CRL有问题,可以用 openssl crl -in crl.pem -inform PEM -outform DER -out crl.der 转成DER格式,然后用十六进制工具看看原始数据。我曾经用这个方法发现过CRL里混入了多余的空格字符。

3.5 核心流程:从CA到CRL的完整链路

下面这张图展示了CRL生成和验证的完整流程,我建议你仔细看看:

CRL生成与验证核心流程 CA私钥 (ca-key.pem) CA证书 (ca-cert.pem) 吊销列表数据 openssl ca -gencrl CRL文件 (crl.pem) openssl crl -CAfile 验证通过/失败 关键点 • 私钥必须保密 • CRL必须由同一CA签名 • 验证时CA证书必须匹配 常见错误 • Issuer不匹配 • 算法不一致

3.6 批量吊销与CRL更新

实际工作中,你不会只吊销一两个证书。我建议你维护一个吊销索引文件,每次吊销证书时往里面追加记录。OpenSSL默认使用 index.txt 来管理吊销状态。

吊销证书的命令:

# 吊销证书(需要证书文件)
openssl ca -revoke cert-to-revoke.pem \
  -config /etc/pki/tls/openssl.cnf \
  -keyfile ca-key.pem \
  -cert ca-cert.pem

吊销后,重新生成CRL:

# 生成包含最新吊销信息的CRL
openssl ca -gencrl \
  -config /etc/pki/tls/openssl.cnf \
  -keyfile ca-key.pem \
  -cert ca-cert.pem \
  -crldays 14 \
  -out crl-updated.pem
注意:每次吊销证书后,必须重新生成CRL并分发到客户端。我曾经见过一个团队,吊销了证书但忘了更新CRL,结果那个证书在CRL过期前一直被认为是有效的。嗯,这种低级错误千万别犯。

3.7 本章小结

这一章我们亲手用OpenSSL生成了CRL,查看了它的内部结构,还验证了签名。你想想看,整个过程其实不复杂,但每一步都有坑。我个人建议你把上面的命令在测试环境里跑一遍,看看输出结果,再故意改一下CRL文件试试签名验证会不会报错。只有亲手踩过坑,才能真正记住。