证书链齐全、域名也对,OpenSSL verify却报CA certificate key too weak。问题可能不是缺链,而是某层公钥强度达不到验证策略。本文用auth_level固定门槛,分清叶子与CA弱密钥,再换对应材料,不把安全等级往下拧。
一、先看EE还是CA,不要只盯网站证书
EE certificate key too weak指向终端证书公钥;CA certificate key too weak指向链中CA公钥。本次OpenSSL 1.1.1k FIPS隔离实验分别观察到error 66和error 67。它们是X.509验证错误号,不是进程退出码:本机两类失败的Shell退出码都是2。
depth=0是待验证的叶子,depth=1是直接签发者,之后逐级向上。根证书也可能因公钥太弱被拒绝;放进信任文件不等于获得强度豁免。先保存完整subject、depth与错误原文,别把所有67都叫"中间证书错误"。

二、把公钥长度与签名算法分开看
约定leaf.pem是叶子,intermediate.pem是直接签发者,root.pem是已确认可信的根。每个文件只放一张待观察证书;多级链逐张检查,不能用x509只读fullchain首张就宣布全链正常。
bash
# 记录运行库,并分别查看各层证书
openssl version -a
for cert in leaf.pem intermediate.pem root.pem; do
openssl x509 -in "$cert" -noout -subject -issuer -text || exit 1
done
输出里的Public-Key表示该证书公钥长度,Signature Algorithm描述签发者如何签署它。给1024位RSA公钥的证书换成SHA-256签名,并不会把公钥变成2048位。密钥长度、签名摘要和证书用途是不同字段,不能"补一个SHA-256"包治百病。
服务可能链接另一版本的库,应单独记录;本文只验证离线链,不冒充目标服务实测。
三、显式设置auth_level,避免默认值打架
bash
openssl verify -no-CApath -CAfile root.pem \
-untrusted intermediate.pem -auth_level 2 -show_chain leaf.pem
-auth_level控制证书链认证安全等级,影响可接受的公钥与签名强度。官方等级定义中,level 2要求至少112位等效安全强度,RSA密钥小于2048位不满足;level 3提高到128位,RSA至少3072位。这里的112位不是RSA模数长度,别把两种"位数"混为一谈。
-CAfile指定可信材料,-untrusted提供候选链;-no-CApath排除默认目录参与。显式策略适合复现,不代表所有环境默认都是2。verify文档的未设置等级,与TLS库编译默认值、应用配置及系统密码策略要分别核对。
auth_level不是TLS协议或密码套件的完整配置。离线通过只能说明这些输入在本次验证条件下通过,不能推出线上协商一定成功。
四、隔离对照:强叶子也救不了弱CA
本次在临时目录生成仅供实验的根、签发CA与叶子,签名统一使用SHA-256,不更改系统信任库,也不监听生产端口。全链RSA 2048位在level 2通过。只将直接签发CA换成RSA 1024位,叶子仍为2048位,验证在depth=1报67。
同一弱CA测试链在level 1下通过,只用于确认"策略门槛"这个变量,不是修复建议。另一组仅把叶子换成1024位,观察到depth=0报66。再把1024位自签根直接放进CAfile,仍在depth=1报67。
这组对照说明,不能只更新站点密钥,也不能靠"已经信任这个根"解释弱密钥可接受。结果有明确版本边界;其他版本、发行版策略可能先报别的错误,应保留全部诊断。
| 现象 | 核对对象 | 处理方向 |
|---|---|---|
| 66,EE key too weak | 叶子公钥与当前等级 | 生成合规新密钥并重签叶子 |
| 67,CA key too weak | 对应depth的CA公钥 | 由CA维护方更换合规链 |
| signature digest too weak | 证书签名摘要与策略 | 不等同于公钥长度问题 |
| 20,找不到签发者 | 候选链与可信根 | 先补齐可信路径再判断强度 |
五、正确修复是换密钥与重签,不是改位数标签
若问题在叶子,应按业务策略生成新密钥、提交新CSR并获得匹配证书。以下只是候选密钥生成示例,先在空的受控工作目录确认candidate.key不存在;不要拿它直接覆盖运行中的文件。
bash
# 只生成候选新密钥,不覆盖现有私钥
umask 077
openssl genpkey -algorithm RSA \
-pkeyopt rsa_keygen_bits:3072 -out candidate.key
3072位只是RSA示例,不代表所有系统必须照抄;算法、长度与性能需满足组织策略及客户端兼容要求。生成密钥不等于完成签发,更不等于部署成功。新私钥应限制访问,不能贴到工单或日志里。
若问题在CA层,联系CA维护方取得符合策略的签发链;更换CA密钥后通常涉及重新签发下级证书与迁移信任。仅给同一弱CA公钥换个有效期、重复下载原链,不能提高它的强度。不要为了让路径缩短就把不可信中间证书塞进根库。
六、不要把降级通过写成修复完成
把等级降到0、关闭证书验证或修改全局密码策略,会改变接受条件,不会改变证书材料。排障时若必须做受控对照,应限定离线测试、记录前后策略,并恢复正式门槛;生产变更另走审批,不能把临时放行留在配置里。
官方verify文档区分了信任锚的签名强度检查边界,但链内所有证书公钥仍需满足指定强度。这也是弱根实验仍失败的原因。公钥强度通过后,仍要继续检查时间、用途、名称与信任来源。
七、保持正式门槛做联合验收
bash
if openssl verify -no-CApath -CAfile root.pem \
-untrusted intermediate.pem -auth_level 2 \
-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是保留测试域名,实际验收替换为业务名称。包装器同时检查等级、服务端用途和名称,将失败返回给调用者;日志路径不可写也会进入失败分支,不应误诊成证书太弱。本次已重放正文代码,并验证弱CA和日志写入失败均不能继续。
之后再用真实客户端连接实际TLS终点,确认服务提供的是新链。若离线成功、线上失败,继续核对实际链、服务运行库和生效策略,而不是反复修改已通过的本地文件。
八、交付前留这几份证据
- 完整错误、depth、库版本和显式认证等级。
- 各层最终证书的公钥算法、长度、签名算法与指纹。
- 新密钥与重签证书的受控交付记录,不包含私钥内容。
- 正式策略下的离线验收及目标客户端TLS验收,两者分开记录。
参考:OpenSSL verify、安全等级定义、x509字段查看。按实际版本复核,不把测试环境通过当作生产承诺。