根证书已经放进CAfile,证书没过期,OpenSSL却报certificate rejected。先别急着下载另一份fullchain:这里的rejected不等于revoked。前者可能是本地信任材料明确拒绝某种用途,后者才是吊销检查的结果。本文用隔离证书区分error 28、辅助信任属性和证书本体。
一、先读完整错误,不把28当成吊销
OpenSSL的X509_V_ERR_CERT_REJECTED表示根CA被标记为拒绝指定用途。它与error 23的certificate revoked、error 20的构链失败、error 26的用途不兼容不是同一个问题。错误编号也不是Shell进程退出码:本轮28对应verify退出2。
临时根直签叶子的实验在depth 1报错;存在中间CA时层级会变。先把错误前的subject与实际路径对应,不把所有depth 1都叫根。

二、先确认读到的CA文件和运行版本
记录运行版本、工作目录及CAfile绝对路径。终端、容器和服务可能读取不同材料。下面root-reject.pem是单张CA工作副本,不是系统文件。
bash
openssl version -a
openssl x509 -in root-reject.pem -noout -text
在文本末尾找Trusted Uses与Rejected Uses。实验中的拒绝属性显示TLS Web Server Authentication。PEM头可能是BEGIN TRUSTED CERTIFICATE,但这个词不是"安全通行证":它也能封装明确拒绝用途的属性。
x509通常只读取首张证书。CA包里有多张时,应逐张核对条目、指纹、来源与辅助属性;只看到第一张正常,不能断言整包无拒绝项。不要将原始日志中的内部名称、路径和业务标识直接公开。
三、把验证用途写清楚,再复现同一故障
下例假定已准备PEM叶证书leaf.pem、单张根CA工作副本,并且叶子名称是占位域名service.example。若有中间CA,需要另提供-untrusted链材料;本例是根直签,不能照搬成缺中间证书的生产配置。
bash
openssl verify -no-CApath -CAfile root-reject.pem \
-purpose sslserver -verify_hostname service.example leaf.pem
-purpose sslserver检查服务器用途,-verify_hostname检查名称,-no-CApath避免默认CA目录掩盖对照。显式CAfile固定本次文件来源,但仍要留意构建、配置与应用自己的验证选项。OpenSSL从1.1.0起,未单独指定信任模型时会从purpose推导模型。
本轮在1.1.1k FIPS构建中,把-purpose删掉后同一拒绝材料竟能通过。这个"绿灯"不是修好了,而是测试条件变了。排障最怕把考题删掉,再宣布满分。正式验收应与应用用途一致,不用取消用途检查解决28。
四、为什么指纹相同,验证结果却不同
OpenSSL辅助信任属性保存在本地可信证书表示中,不是CA签名覆盖的X.509扩展。证书本体相同,不代表本地信任决策相同;只比SHA-256证书指纹会漏掉这一层。
下面只在独立实验目录对临时CA副本添加拒绝项,不能对系统或生产CA执行。root.pem须是已有的实验CA,命令不创建完整PKI,也不是让读者把真实根证书加入黑名单。
bash
openssl x509 -in root.pem -addreject serverAuth \
-trustout -out root-reject.pem
openssl x509 -in root-reject.pem -noout -sha256 -fingerprint
openssl x509 -in root.pem -noout -sha256 -fingerprint
本轮两份证书的指纹与证书DER均相同,带serverAuth拒绝项的材料却验证失败。辅助属性不是证书签名或叶子EKU。指纹确认对象,辅助属性确认本地策略,要一起留档。
五、用正反例区分策略问题与用途扩展
实验用临时RSA根直签一张同时具有serverAuth和clientAuth用途的叶证书,排除叶子EKU干扰。下表是本轮离线结果,不代表所有TLS后端、系统证书库或浏览器行为。
| 根CA工作副本 | 验证条件 | 本轮结果 |
|---|---|---|
| 没有辅助属性 | sslserver | 通过,退出0 |
| 拒绝serverAuth | sslserver | error 28,depth 1,退出2 |
| 拒绝clientAuth | sslserver | 通过,退出0 |
| 拒绝clientAuth | sslclient | error 28,退出2 |
| 同时信任和拒绝serverAuth | sslserver | 仍为error 28 |
再加一个trusted用途并不能抵消同用途的reject。也不要把Rejected Uses与证书里的Extended Key Usage混为一谈:前者描述本地信任政策,后者是签名证书中的扩展;两者都可能影响验证,但修复责任与材料来源不同。
六、修复靠授权来源,不靠清掉拒绝项
如果拒绝项来自组织策略、CA撤信任或安全事件,应停止使用该信任路径,联系证书与信任库维护者确定允许的替代链。若是配置误发,也应从受控来源恢复经过批准的材料,记录变更原因和回滚版本,而不是在客户端偷偷放宽政策。
尤其小心"转一下PEM格式"。x509默认输出普通证书时可能丢弃辅助信任设置;本轮把拒绝材料普通读写后,服务器验证确实变成通过。这证明策略丢了,不证明风险消失。需要保留可信表示时核对-trustout与完整属性,别把格式转换当解除拒绝的捷径。
下例在可信、任务专用目录运行,root-approved.pem来自已批准来源;日志路径不能被其他用户写入,避免覆盖业务文件或跟随不可信软链接。
bash
if openssl verify -no-CApath -CAfile root-approved.pem \
-purpose sslserver -verify_hostname service.example \
leaf.pem >verify.log 2>&1; then
printf '%s\n' '离线链验证通过,仍需验收真实HTTPS'
else
rc=$?
printf '验证或日志写入失败:%s\n' "$rc" >&2
exit "$rc"
fi
本轮重放了四段正文命令,正确材料通过;拒绝CA、错误名称和日志路径无法打开均阻止相应验收通过。脚本保留失败退出码,不因为日志文件存在就判成功。它只验离线链,还没有完成网络请求。
七、上线前按这张清单收口
- 准确区分rejected与revoked,保存错误号、depth、subject及进程退出码。
- 核对实际CA来源、全部相关条目、辅助信任属性与应用用途,不只比指纹。
- 通过授权流程恢复信任材料,不删purpose、不清拒绝项、不关闭验证。
- 恢复后验证名称、用途、完整链;再检查实际HTTPS终点、应用重载和业务响应。
实验仅使用临时目录做离线验证,证书与私钥已清理,未修改系统信任库、时钟或服务。未实测生产HTTPS、浏览器及3.x运行时。3.0官方文档用于解释信任锚规则,不把文档阅读冒充新版本实测。