中间证书文件明明在,OpenSSL verify却报invalid CA certificate,有时紧跟着key usage does not include certificate signing。先别忙着再拼一份fullchain:找到签发者,不等于它有资格签证书。这里从basicConstraints和keyUsage入手,区分缺链、CA资格和用途限制,最后给出可留档的验证方式。
一、error 24不是"所有证书错误"的统称
invalid CA certificate表示验证链中的CA未满足相应CA要求。本机OpenSSL 1.1.1k FIPS实验中,错误号为24;key usage does not include certificate signing对应32。这两个数字是X.509验证错误号,不是Shell退出码。
错误文字比"证书无效"具体。error 20关注签发者是否找到;error 7关注签名验证;24与32提醒检查签发者的CA标识和密钥用途。它们可能同时出现,不能只截第一行。

二、先定位失败的证书,再看扩展
下面约定leaf.pem是叶子,intermediate.pem是直接签发者,root.pem是可信根。多级链应逐张检查,不要把fullchain第一张当整条链。
bash
openssl version
openssl x509 -in intermediate.pem -noout -subject -issuer -serial
openssl x509 -in intermediate.pem -noout -text
depth=0是目标证书,depth=1是直接签发者,向上递增。看到depth=1,就结合subject核对中间证书,而不是修改叶子的扩展。x509能显示字段只说明可解析,不表示签发权限或验证通过。
重点看Basic Constraints与Key Usage。Certificate Sign对应keyCertSign;Digital Signature不是它的别名。两者都带"签名",权限却不同。
三、CA:TRUE与keyCertSign分别管什么
RFC 5280规定,对用于验证证书签名的CA证书,basicConstraints应按规范包含CA标识;对于v3证书,缺失该扩展或cA未置真,不能将其公钥用于验证证书签名。合规CA签发此类CA证书时,应将basicConstraints标为critical。
若该扩展存在,验证证书签名必须允许keyCertSign。digitalSignature不能代替它;cRLSign也不能单独代替证书签名权限。
没有keyUsage扩展,不等于存在扩展但缺少keyCertSign。本机普通验证中,前一种测试链能通过,后一种失败。实现接受和配置合规要分开判断。
四、固定信任材料,复现真正的错误
bash
openssl verify -no-CApath -CAfile root.pem \
-untrusted intermediate.pem -show_chain leaf.pem
-CAfile指定信任材料,-no-CApath避免默认目录补链,-untrusted只提供候选链,不会赋予中间证书额外权限。
保留输出、版本和输入指纹。同名候选CA或交叉签名可能改变选链。subject与issuer相接只是线索,不能代替签名、扩展与信任验证。
如果先报缺链,先恢复候选链;若已定位24或32,再审查扩展。-x509_strict不是修复开关;开启后应记录新增诊断,不能关闭严格模式冒充正确。
五、隔离实验:CA:TRUE也可能失败
本次在临时目录生成测试根、直接签发者和叶子证书,未修改系统信任库,未连接生产服务。保持叶子不变,只更换签发者扩展。正确组合验证通过。
将签发者设为CA:FALSE且只允许digitalSignature,在depth=1观察到24与32。改为CA:TRUE但仍只允许digitalSignature,结果仍有24与32。可见CA:TRUE不是充分条件。
另一组CA:TRUE省略keyUsage在verify下通过;缺链报20。结果仅代表本版,不承诺他库或浏览器顺序。
六、修签发模板,不要手改已签证书
若确实需要一个只能直接签发终端证书的中间CA,可由上级CA按受控策略采用类似扩展节:
ini
[issuing_ca]
basicConstraints = critical,CA:TRUE,pathlen:0
keyUsage = critical,keyCertSign,cRLSign
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
这只是扩展片段,不是完整CA配置或生产签发命令;本文用隔离脚手架验证了它。CSR请求哪些扩展,不代表CA已批准或最终证书必然包含它们。
pathlen:0仍允许直接签发叶子,但不允许其下再出现非自颁发中间CA。cRLSign仅在确有签CRL职责时保留。修复应由合法上级按审批重新签发合适的CA证书,再交付匹配的链;不能给普通网站证书随手加CA:TRUE,也不能编辑已签PEM里的字段,指望原签名继续有效。
| 现象 | 重点检查 | 不能替代的操作 |
|---|---|---|
| 24,invalid CA certificate | 失败depth处的CA扩展与用途 | 只反复拼接fullchain |
| 32,certificate signing | keyUsage是否允许keyCertSign | 增加serverAuth或digitalSignature |
| 20,找不到签发者 | 候选链与可信根 | 直接断言CA:FALSE |
| 25,路径长度超限 | CA层级与pathlen | 只增加keyCertSign |
七、链通过后,再验用途与名称
bash
if openssl verify -no-CApath -CAfile root.pem \
-untrusted intermediate.pem -purpose sslserver \
-verify_hostname api.example.test leaf.pem >verify.log 2>&1; then
printf 'offline verification passed\n'
else
rc=$?
printf 'verification failed: rc=%s; see verify.log\n' "$rc" >&2
exit "$rc"
fi
api.example.test是保留测试域名,实际验收需改为真实业务名称。脚本同时检查服务端用途与主机名,并将失败退出码交给调用者;日志重定向失败也必须阻止流程继续,需检查目录和磁盘,而不是归因为证书错误。
serverAuth属于extendedKeyUsage,不是给CA颁发签证书权限。链验证成功之后,叶子仍可能因用途、名称或时间失败,修一处不等于所有关卡都通过。离线验证也不能替代目标客户端的真实TLS握手。
八、交付前的检查清单
- 保存完整错误与depth,明确失败的是叶子、直接签发者还是更高层证书。
- 核对最终证书中的CA标识和keyUsage,而不只看CSR或配置文件。
- 确认重新签发材料来源可信,未扩大信任范围,未关闭验证。
- 离线链、用途与名称验证通过后,再验证实际服务终点和目标客户端;日志不含私钥或内部凭据。
参考:OpenSSL verify、X.509扩展配置、RFC 5280第4.2.1.3与4.2.1.9节。按实际运行库版本复核行为。