4、CA二级证书:生成CA证书请求、使用根证书签发二级CA、验证证书链
上一章我们搭好了根CA,但说实话,根CA的私钥太金贵了。我一般把它锁在离线机器里,平时签发证书根本不动它。那日常签发工作谁来做?二级CA。
二级CA,也叫中间CA。它由根CA签发,拿着它去签发终端设备证书。这样就算二级CA私钥泄露,吊销它就行,根CA还是安全的。说白了,就是分层管理,风险隔离。
4.1 生成二级CA的私钥和证书请求
先给二级CA生成一对密钥。我个人习惯用ECC,性能好、密钥短。当然RSA也行,看你们公司的安全策略。
# 生成二级CA的私钥(ECC P-256)
openssl ecparam -genkey -name prime256v1 -out intermediate.key
# 查看私钥信息
openssl ec -in intermediate.key -text -noout
私钥生成后,权限一定要锁死。我见过有人把中间CA的私钥权限设成644,结果被运维脚本误删了……嗯,血的教训。
接下来生成证书请求(CSR)。这里要注意,二级CA的CN(Common Name)最好和根CA区分开,比如用「Company Intermediate CA v1」。
# 生成二级CA的证书请求
openssl req -new \
-key intermediate.key \
-out intermediate.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/CN=MyCompany Intermediate CA v1"
4.2 使用根证书签发二级CA
现在拿着根CA的私钥和证书,来签这个二级CA的请求。签发时有个关键参数——pathlen:0。什么意思?就是限制二级CA不能再签下一级CA,只能签终端证书。这样能防止证书链无限延伸。
# 使用根CA签发二级CA证书(有效期10年)
openssl x509 -req \
-in intermediate.csr \
-CA root.crt \
-CAkey root.key \
-CAcreateserial \
-out intermediate.crt \
-days 3650 \
-sha256 \
-extfile <(echo "
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, keyCertSign, cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
")
签发完成后,你会得到一个 intermediate.crt。这就是二级CA证书。你可以用下面命令看看它的内容:
openssl x509 -in intermediate.crt -text -noout | grep -E "CA:|Path"
输出里应该能看到 CA:TRUE 和 Path Length Constraint:0。这就对了。
4.3 验证证书链
证书签完了,链能不能串起来?必须验证。验证分两步:一是看二级CA是不是由根CA签发,二是看整个链是否可信。
4.3.1 验证二级CA的签发者
# 验证二级CA证书的签发者
openssl verify -CAfile root.crt intermediate.crt
如果输出 intermediate.crt: OK,说明根CA认这个二级CA。如果报错,八成是签发时扩展字段写错了,或者证书链文件没拼对。
4.3.2 构建完整证书链文件
实际部署时,客户端需要拿到完整的证书链,才能验证到根。所以我们要把根证书和二级CA证书拼在一起。
# 构建证书链文件(根证书在前,二级CA在后)
cat root.crt intermediate.crt > chain.crt
# 验证证书链
openssl verify -CAfile chain.crt intermediate.crt
这里有个细节:chain.crt 的顺序是「根证书 → 二级CA证书」。有些设备要求反过来,你部署前最好查一下文档。
OK— 证书链完整,信任关系建立unable to get local issuer certificate— 缺少中间CA或根证书certificate has expired— 证书过期,检查有效期self-signed certificate in chain— 根证书自签名正常,但链可能不完整
4.4 证书链结构图
下面这张图展示了根CA、二级CA和设备证书之间的层级关系。我画图时习惯把根CA放在最上面,二级CA在中间,设备证书在最下面。箭头表示「签发」关系。
你看,从设备证书往上追溯,每一级都由上一级签发,最终停在自签名的根CA。这就是信任链的传递。客户端验证时,只要信任根CA,就能信任整条链上的所有证书。
4.5 避坑指南
做二级CA签发,有几个坑我替你们踩过了:
- 扩展字段遗漏: 二级CA必须带
CA:TRUE和pathlen:0。漏了其中一个,客户端会认为它不是合法CA,拒绝信任。 - 证书链顺序搞反: 有些服务器(比如Nginx)要求证书链文件里「服务器证书在前,中间证书在后」。但OpenSSL的
-CAfile要求「根证书在前」。不同场景顺序不同,务必看文档。 - 私钥权限太松: 二级CA私钥至少设成
400(仅所有者可读)。我曾经见过一个测试环境,中间CA私钥是644,被CI脚本意外覆盖了……嗯,那天下午我都在重签证书。 - 有效期超过根CA: 二级CA过期了,根CA还在。但所有由二级CA签发的设备证书都会失效。所以二级CA的有效期一定要小于根CA。
intermediate.crt 和 chain.crt 一起归档,并记录签发日期、有效期、用途。方便后续审计和续期。