Java 怎么判断一条证书链可信?缺中间证书、证书过期、CA 约束被违反会怎样?这篇用 keytool 造出一棵真实的证书树,逐个用 CertPathValidator 验证,看每种失败的 reason 与出错的证书位置。
证书链(叶子在前,不含根):leaf ← Demo Intermediate(pathlen:0)← Demo Root(信任锚) 正常链 [leaf, ica],信任 root(撤销检查关闭)→ 通过,信任锚 = Demo Root,叶子的公钥算法 EC 缺中间证书 [leaf],信任 root → CertPathValidatorException: Path does not chain with any of the trust anchors(原因 NO_TRUST_ANCHOR,出问题的证书在链中的下标 -1) 链里把根也放进去 [leaf, ica, root],信任 root → 通过,信任锚 = Demo Root,叶子的公钥算法 EC 链的顺序放反 [ica, leaf],信任 root → CertPathValidatorException: Path does not chain with any of the trust anchors(原因 NO_TRUST_ANCHOR,出问题的证书在链中的下标 -1) 信任了另一个根 other → CertPathValidatorException: Path does not chain with any of the trust anchors(原因 NO_TRUST_ANCHOR,出问题的证书在链中的下标 -1) 把中间证书当作信任锚(信任 ica,链只有 [leaf])→ 通过,信任锚 = Demo Intermediate,叶子的公钥算法 EC 叶子的有效期:Sat Oct 03 18:49:18 CST 2026 ~ Fri Jul 30 18:49:18 CST 2027
过期的叶子 [exp, ica],信任 root(今天)→ CertPathValidatorException: validity check failed(原因 EXPIRED,出问题的证书在链中的下标 0) 同一个过期的叶子,把验证时间设在叶子自己的有效期内 Fri Sep 04 18:49:20 CST 2026(这时中间证书还没有生效)→ CertPathValidatorException: validity check failed(原因 NOT_YET_VALID,出问题的证书在链中的下标 1) 正常链,把验证时间设成 400 天以后(叶子 300 天、中间证书 365 天有效期都已结束)→ CertPathValidatorException: validity check failed(原因 EXPIRED,出问题的证书在链中的下标 1) X509Certificate.checkValidity() 对正常叶子:通过 X509Certificate.checkValidity() 对过期叶子 → CertificateExpiredException: NotAfter: Tue Sep 08 18:49:20 CST 2026
pathlen:0 的中间证书下面又挂了一层子 CA [leaf2, ica2, ica],信任 root → CertPathValidatorException: basic constraints check failed: pathLenConstraint violated - this cert must be the last cert in the certification path(原因 PATH_TOO_LONG,出问题的证书在链中的下标 1) 中间证书的 keyUsage 只有 digitalSignature(没有 keyCertSign)[leaf3, noku_ica] → CertPathValidatorException: CA key usage check failed: keyCertSign bit is not set(原因 INVALID_KEY_USAGE,出问题的证书在链中的下标 1) 中间证书的 basicConstraints 是 CA:false [leaf4, notca] → CertPathValidatorException: basic constraints check failed: this is not a CA certificate(原因 NOT_CA_CERT,出问题的证书在链中的下标 1) ica 的 basicConstraints pathLen = 0,keyUsage keyCertSign = true
撤销检查 开启(默认 true),没有 CRL 与 OCSP 可用,链 [leaf, ica] → CertPathValidatorException: Could not determine revocation status(原因 UNDETERMINED_REVOCATION_STATUS,出问题的证书在链中的下标 1) SOFT_FAIL → CertPathValidatorException: Certificate does not specify OCSP responder ← CertPathValidatorException: Certificate does not specify OCSP responder ONLY_END_ENTITY + SOFT_FAIL → CertPathValidatorException: Certificate does not specify OCSP responder ← CertPathValidatorException: Certificate does not specify OCSP responder 不检查撤销时,验证 [leaf, ica] 这条链 2000 次:每次 835 μs(含读 PEM 文件与解析,不是纯验证)