3. 后量子密码部署排障:混合证书链中 PQC 证书与 RSA 中间证书顺序错误
故障现象与链结构判断
部署完成后,服务端在 TLS 握手中下发的证书链为:ML-DSA 终端证书 → RSA 中间证书,但根 CA(RSA 信任锚)未随链下发。部分客户端(尤其是只信任系统根库、不做 AIA 补链的客户端)报 unable to get local issuer certificate 或“证书链不完整”。核心问题有两层:链内顺序(终端证书必须在前,签发者依次在后)与信任锚可达性(链尾的 RSA 中间证书必须能由客户端本地根库中的根 CA 签发验证)。
定位过程:用 openssl verify 与链构建日志分离两类问题
先取服务端实际下发的链,再分别验证“顺序”和“信任锚”两个假设。以下命令在服务端证书目录执行,fullchain.pem 为当前下发链,root.pem 为根 CA。
# 1) 查看链中各证书的 subject / issuer,确认顺序
openssl crl2pkcs7 -nocrl -certfile fullchain.pem \
| openssl pkcs7 -print_certs -noout
# 期望输出(正确顺序):
# subject=C = CN, O = Demo, CN = server.example <- leaf (ML-DSA)
# issuer=C = CN, O = Demo, CN = Demo RSA Intermediate
# subject=C = CN, O = Demo, CN = Demo RSA Intermediate
# issuer=C = CN, O = Demo, CN = Demo Root CA
# 2) 按“链内顺序 + 信任锚”验证
openssl verify -CAfile root.pem -untrusted fullchain.pem leaf.pem
# 顺序错时典型输出:
# error 20 at 0 depth lookup: unable to get local issuer certificate
# 缺锚时典型输出:
# error 2 at 1 depth lookup: unable to get issuer certificate
若 crl2pkcs7 输出中第一段是 RSA 中间证书、第二段才是 ML-DSA 终端证书,即为顺序错误;若顺序正确但 verify 仍报 error 2,则检查 root.pem 是否真的是链尾中间证书的签发者(比对 subject/issuer 与 AKI/SKI)。
修复:重排链并显式配置信任锚
把终端证书放第一段、中间证书依次在后,根 CA 不放入下发链(由客户端本地信任库提供),并在服务端显式指定信任锚文件用于 OCSP/验证辅助。
# 重排:leaf 在前,intermediate 在后
cat leaf.pem intermediate.pem > fullchain.pem
# Nginx 配置:下发链只含 leaf + intermediate
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/leaf.key;
ssl_trusted_certificate /etc/nginx/certs/root.pem; # 仅用于验证/OCSP,不下发
# 重载并复核
nginx -t && nginx -s reload
openssl verify -CAfile root.pem -untrusted fullchain.pem leaf.pem
# 期望:leaf.pem: OK
若客户端仍报链不完整,用
openssl s_client -connect host:443 -showcerts 确认第一段证书的 subject 等于服务域名,且链尾 issuer 能在客户端根库中找到;必要时在服务端补发 AIA 或提供中间证书下载。验证与判读
| 检查项 | 命令/观察点 | 通过判据 |
|---|---|---|
| 链内顺序 | pkcs7 -print_certs 首段 subject | 等于服务域名(leaf 在前) |
| 签发关系 | 逐段比对 issuer 与下一段 subject | 逐级匹配,无断点 |
| 信任锚 | verify -CAfile root.pem | 输出 OK |
| 实际下发 | s_client -showcerts | 第一段为 ML-DSA leaf,链尾为 RSA 中间证书 |