You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java签名验证中如何获取证书吊销时间且不中断验证流程

解决方案:利用PKIX吊销检查器的软失败模式实现无中断验证并获取吊销日期

我之前在做证书链验证的需求时,刚好碰到过和你一样的问题——默认的CertPathValidator碰到吊销证书就直接抛异常中断流程,根本没法拿到吊销日期做对比。后来摸索出了利用PKIX吊销检查器的**软失败(Soft Fail)**模式来实现需求,下面是具体的实现思路和代码:

核心思路

Java的PKIX验证框架允许我们自定义吊销检查的行为,通过给PKIXRevocationChecker设置SOFT_FAIL选项,验证过程不会因为遇到吊销证书或无法获取吊销信息而抛出异常,而是会把所有证书的吊销状态收集起来,供我们后续处理。

具体实现步骤

1. 初始化PKIX验证参数并配置吊销检查器

首先我们需要初始化信任库和PKIX参数,然后获取默认的吊销检查器并修改其行为:

// 加载你的信任库(示例代码,实际需根据你的场景调整)
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
try (InputStream is = new FileInputStream("truststore.jks")) {
    trustStore.load(is, "password".toCharArray());
}

// 初始化PKIX参数
PKIXParameters params = new PKIXParameters(trustStore);
params.setRevocationEnabled(true); // 必须启用吊销检查,否则不会执行吊销验证

// 获取默认的PKIX吊销检查器
PKIXRevocationChecker revocationChecker = (PKIXRevocationChecker) params.getRevocationChecker();
// 设置SOFT_FAIL选项:遇到吊销证书或无法获取CRL/OCSP时不抛出异常,继续验证
revocationChecker.setOptions(EnumSet.of(PKIXRevocationChecker.Option.SOFT_FAIL));

// 将修改后的检查器放回参数中
params.setRevocationChecker(revocationChecker);

2. 执行证书链验证

接下来调用CertPathValidator执行验证,此时即使链中有吊销证书,也不会抛出异常:

CertPathValidator validator = CertPathValidator.getInstance("PKIX");
// 这里的certPath是你要验证的证书链
PKIXCertPathValidatorResult validationResult = 
    (PKIXCertPathValidatorResult) validator.validate(certPath, params);

3. 提取吊销信息并对比签名时间

验证完成后,我们可以从吊销检查器中获取所有证书的吊销状态,筛选出已吊销的证书并拿到吊销日期,再和签名时间对比:

// 获取所有证书的吊销结果
Map<X509Certificate, PKIXRevocationChecker.RevocationStatus> revocationResults = 
    revocationChecker.getRevocationResults();

// 遍历结果,处理已吊销的证书
for (Map.Entry<X509Certificate, PKIXRevocationChecker.RevocationStatus> entry : revocationResults.entrySet()) {
    X509Certificate cert = entry.getKey();
    PKIXRevocationChecker.RevocationStatus status = entry.getValue();

    if (status instanceof PKIXRevocationChecker.RevokedStatus) {
        // 证书已被吊销,提取吊销日期
        PKIXRevocationChecker.RevokedStatus revokedStatus = (PKIXRevocationChecker.RevokedStatus) status;
        Date revocationDate = revokedStatus.getRevocationDate();
        
        // 这里替换成你的签名时间获取逻辑(比如从CMS/JWS签名中提取)
        Date signingTime = getSigningTimeFromSignature();
        
        // 对比吊销日期和签名时间
        if (revocationDate.before(signingTime)) {
            System.out.printf("证书 %s 在签名时未被吊销(吊销日期:%s,签名日期:%s)%n", 
                cert.getSubjectDN(), revocationDate, signingTime);
        } else {
            System.out.printf("证书 %s 在签名时已被吊销(吊销日期:%s,签名日期:%s)%n", 
                cert.getSubjectDN(), revocationDate, signingTime);
        }
    } else if (status instanceof PKIXRevocationChecker.UnknownStatus) {
        // 无法获取该证书的吊销状态(比如CRL/OCSP服务不可达)
        System.out.printf("无法确定证书 %s 的吊销状态%n", cert.getSubjectDN());
    }
    // 若为ValidityStatus,则证书未被吊销,无需处理
}

注意事项

  • Java版本要求:PKIXRevocationChecker是Java 7及以上版本才有的API,确保你的项目使用的Java版本符合要求。
  • 签名时间获取:签名时间需要从你的签名数据中提取,比如CMS签名可以从SignerInfo的signingTime属性获取,JWS签名可以从header的iat字段获取。
  • 时区问题:对比日期时要确保吊销日期和签名时间使用的是同一时区(建议统一使用UTC),避免出现时间对比错误。
  • OCSP/CRL支持:默认的吊销检查器会自动处理CRL和OCSP两种吊销方式,如果你需要指定仅使用某一种,可以通过调整检查器的参数实现。

内容的提问来源于stack exchange,提问作者Lucas Grijander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:29:39