bigywater.tech
Java · 358

CRL 与 OCSP:证书撤销状态

证书吊销检查的结果不只是「好」与「坏」,还有「查不到」。这篇在本机搭起真实的 CRL 与 OCSP 服务,把各种选项在服务正常、过期、停掉时的行为逐个跑出来。

SOFT_FAIL 放行
响应器停掉时,SOFT_FAIL 让已吊销的 leaf2 也通过验证(记录 1 条软失败)
0 → 1 次
默认 PKIXParameters 不加 enableCRLDP 时 CRL 服务器收到的请求(0),与加上之后(1)
268 → 707986 字节
2 条与 20002 条吊销记录的 CRL 大小

CRL 文件本身

实测 · 本机执行输出
  [crl]
    CRL:发布者 O=Demo,CN=Revoke Test CA;thisUpdate 2026-10-03T19:21:59Z;nextUpdate 2026-10-10T19:21:59Z;签名算法 SHA256withECDSA;版本 2;DER 长度 268
    已吊销条目数 2
        序列号 1001;吊销时间 2026-10-03T19:21:59Z;原因 KEY_COMPROMISE;扩展 OID [2.5.29.21]
        序列号 1004;吊销时间 2026-10-03T19:21:59Z;原因 CESSATION_OF_OPERATION;扩展 OID [2.5.29.21]
    用 CA 公钥验证 CRL 签名:通过
        c.isRevoked(leaf1,    序列号 1000) = false
        c.isRevoked(leaf2,    序列号 1001) = true
        c.isRevoked(leaf3,    序列号 1002) = false
        c.isRevoked(leafplain, 序列号 1003) = false
    用错误的公钥验证 CRL 签名 → SignatureException: Signature does not match.
    leaf1 的 CRL 分发点扩展:true;AIA(1.3.6.1.5.5.7.1.1)扩展:true;leafplain 两者:false/false
    过期 CRL:thisUpdate 2026-09-01T00:00:00Z;nextUpdate 2026-09-02T00:00:00Z
    → 本次运行里:CRL 服务器收到 GET /ca.crl 0 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.1 s)

只用本地 CRL

实测 · 本机执行输出
  [local2]
    (leafplain / leafrev 没有 CRL 分发点与 AIA 扩展,leafrev 已被吊销,原因 cessationOfOperation)
        本地有效 CRL:leafplain → 通过(41 ms)
        本地有效 CRL:leafrev   → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: CESSATION_OF_OPERATION, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [2.5.29.21];消息:Certificate has been revoked, reason: CESSATION_OF_OPERATION, revocation date: Sun Oct 04 03:
        本地 CRL 已过期:leafplain → 失败:UNDETERMINED_REVOCATION_STATUS ← CertPathValidatorException: Could not determine revocation status;消息:Could not determine revocation status
        本地 CRL 已过期:leafrev   → 失败:UNDETERMINED_REVOCATION_STATUS ← CertPathValidatorException: Could not determine revocation status;消息:Could not determine revocation status
        本地没有 CRL:leafplain → 失败:UNDETERMINED_REVOCATION_STATUS ← CertPathValidatorException: Could not determine revocation status;消息:Could not determine revocation status
        本地没有 CRL:leafrev   → 失败:UNDETERMINED_REVOCATION_STATUS ← CertPathValidatorException: Could not determine revocation status;消息:Could not determine revocation status
        本地没有 CRL + SOFT_FAIL:leafplain → 通过(0 ms);软失败 1 条:[Could not determine revocation status]
        本地没有 CRL + SOFT_FAIL:leafrev   → 通过(0 ms);软失败 1 条:[Could not determine revocation status]
        本地 CRL 已过期 + SOFT_FAIL:leafplain → 通过(0 ms);软失败 1 条:[Could not determine revocation status]
        本地 CRL 已过期 + SOFT_FAIL:leafrev   → 通过(0 ms);软失败 1 条:[Could not determine revocation status]
    本地有效 CRL + 验证时间设为 CRL 签发之前一天(2026-10-02):leafrev → 失败:NOT_YET_VALID ← CertificateNotYetValidException: NotBefore: Sun Oct 04 03:21:59 CST 2026;消息:validity check failed
    → 本次运行里:CRL 服务器收到 GET /ca.crl 0 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.2 s)

CRL 分发点

实测 · 本机执行输出
  [PKIXRevocationChecker(PREFER_CRLS + NO_FALLBACK),不加 JVM 参数]
        leaf1     → 通过(55 ms)
        leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [2.5.29.21];消息:Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority
        leaf3     → 通过(1 ms)
        leafplain → 失败:UNDETERMINED_REVOCATION_STATUS ← CertPathValidatorException: Could not determine revocation status;消息:Could not determine revocation status
    → 本次运行里:CRL 服务器收到 GET /ca.crl 1 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.2 s)
  [同上 + -Dcom.sun.security.enableCRLDP=true](JVM 参数 -Dcom.sun.security.enableCRLDP=true)
        leaf1     → 通过(52 ms)
        leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [2.5.29.21];消息:Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority
        leaf3     → 通过(1 ms)
        leafplain → 失败:UNDETERMINED_REVOCATION_STATUS ← CertPathValidatorException: Could not determine revocation status;消息:Could not determine revocation status
    → 本次运行里:CRL 服务器收到 GET /ca.crl 1 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.2 s)
  [同一 JVM 内验证两遍]
        leaf1     → 通过(50 ms)
        leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [2.5.29.21];消息:Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority
        (同一 JVM 内第 2 次)leaf1     → 通过(0 ms)
        (同一 JVM 内第 2 次)leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [2.5.29.21];消息:Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 
    → 本次运行里:CRL 服务器收到 GET /ca.crl 1 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.2 s)
  [默认 PKIXParameters(无 checker),不加 JVM 参数]
        默认 PKIXParameters leaf1     → 失败:UNDETERMINED_REVOCATION_STATUS ← CertPathValidatorException: Could not determine revocation status
        默认 PKIXParameters leaf2     → 失败:UNDETERMINED_REVOCATION_STATUS ← CertPathValidatorException: Could not determine revocation status
        默认 PKIXParameters leafplain → 失败:UNDETERMINED_REVOCATION_STATUS ← CertPathValidatorException: Could not determine revocation status
    → 本次运行里:CRL 服务器收到 GET /ca.crl 0 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.2 s)
  [默认 PKIXParameters(无 checker)+ enableCRLDP=true](JVM 参数 -Dcom.sun.security.enableCRLDP=true)
        默认 PKIXParameters(revocationEnabled = true,没有自定义 checker)leaf1     → 通过(51 ms)
        默认 PKIXParameters leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [2.5.29.21]
        默认 PKIXParameters leafplain → 失败:UNDETERMINED_REVOCATION_STATUS ← CertPathValidatorException: Could not determine revocation status
    → 本次运行里:CRL 服务器收到 GET /ca.crl 1 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.2 s)

OCSP

实测 · 本机执行输出
  [ocsp(NO_FALLBACK,只用 OCSP)]
        leaf1     → 通过(53 ms)
        leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [];消息:Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo,
        leaf3     → 通过(3 ms)
        leafplain → 失败:UNSPECIFIED ← CertPathValidatorException: Certificate does not specify OCSP responder;消息:Certificate does not specify OCSP responder
    → 本次运行里:CRL 服务器收到 GET /ca.crl 0 次,OCSP 响应器收到请求 3 次(JVM 总耗时 0.2 s)
  [ocsp,同一 JVM 内再验证一遍]
        leaf1     → 通过(49 ms)
        leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [];消息:Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo,
        (同一 JVM 内第 2 次)leaf1     → 通过(2 ms)
        (同一 JVM 内第 2 次)leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [];消息:Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, aut
    → 本次运行里:CRL 服务器收到 GET /ca.crl 0 次,OCSP 响应器收到请求 4 次(JVM 总耗时 0.2 s)
  [默认选项(OCSP 优先,失败回退 CRL)]
        leaf1     → 通过(49 ms)
        leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [];消息:Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo,
        leaf3     → 通过(3 ms)
        leafplain → 失败:UNSPECIFIED ← CertPathValidatorException: Certificate does not specify OCSP responder;消息:Certificate does not specify OCSP responder
    → 本次运行里:CRL 服务器收到 GET /ca.crl 0 次,OCSP 响应器收到请求 3 次(JVM 总耗时 0.2 s)

OCSP 响应器停掉之后

实测 · 本机执行输出
  [OCSP 响应器已停,NO_FALLBACK]
        leaf1     → 失败:UNDETERMINED_REVOCATION_STATUS ← ConnectException: Connection refused;消息:Unable to determine revocation status due to network error
        leaf2     → 失败:UNDETERMINED_REVOCATION_STATUS ← ConnectException: Connection refused;消息:Unable to determine revocation status due to network error
    → 本次运行里:CRL 服务器收到 GET /ca.crl 0 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.2 s)
  [OCSP 响应器已停,默认选项]
        leaf1     → 通过(52 ms)
        leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [2.5.29.21];消息:Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority
    → 本次运行里:CRL 服务器收到 GET /ca.crl 1 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.2 s)
  [OCSP 响应器已停,NO_FALLBACK + SOFT_FAIL]
        leaf1     → 通过(44 ms);软失败 1 条:[Unable to determine revocation status due to network error]
        leaf2     → 通过(4 ms);软失败 1 条:[Unable to determine revocation status due to network error]
        leafrev   → 失败:UNSPECIFIED ← CertPathValidatorException: Certificate does not specify OCSP responder;消息:Certificate does not specify OCSP responder
    → 本次运行里:CRL 服务器收到 GET /ca.crl 0 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.2 s)

CRL 的体积

实测 · 本机执行输出
  [小 CRL(2 条)]
    CRL 文件 ca.crl.der:DER 长度 268 字节;已吊销条目 2;解析耗时 2 ms
    10000 次 isRevoked(leaf1) 总耗时 6 ms(结果 false)
    getRevokedCertificate(leaf1 序列号) = null;一次耗时 0.01 ms
        第 1 次(本地 CertStore)验证 leaf1 → 通过(9 ms)
        第 2 次(本地 CertStore)验证 leaf1 → 通过(0 ms)
        第 3 次(本地 CertStore)验证 leaf1 → 通过(0 ms)
    → 本次运行里:CRL 服务器收到 GET /ca.crl 0 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.1 s)
  [大 CRL(20002 条)]
    CRL 文件 big.crl:DER 长度 707986 字节;已吊销条目 20002;解析耗时 61 ms
    10000 次 isRevoked(leaf1) 总耗时 5 ms(结果 false)
    getRevokedCertificate(leaf1 序列号) = null;一次耗时 0.01 ms
        第 1 次(本地 CertStore)验证 leaf1 → 通过(13 ms)
        第 2 次(本地 CertStore)验证 leaf1 → 通过(1 ms)
        第 3 次(本地 CertStore)验证 leaf1 → 通过(1 ms)
    → 本次运行里:CRL 服务器收到 GET /ca.crl 0 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.3 s)
  [CRL 分发点改为 20002 条的大 CRL 之后再验证]
        leaf1     → 通过(128 ms)
        leaf2     → 失败:REVOKED ← CertificateRevokedException: Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority: O=Demo, CN=Revoke Test CA, extension OIDs: [2.5.29.21];消息:Certificate has been revoked, reason: KEY_COMPROMISE, revocation date: Sun Oct 04 03:21:59 CST 2026, authority
    → 本次运行里:CRL 服务器收到 GET /ca.crl 1 次,OCSP 响应器收到请求 0 次(JVM 总耗时 0.2 s)
  收尾:CRL 与 OCSP 服务已停止

分步演示

CRL 与 OCSP
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12;证书与 CRL 由 OpenSSL 3.6.4 现场生成(EC P-256),CRL 服务器是 python3 http.server(127.0.0.1:9710),OCSP 响应器是 openssl ocsp -index(127.0.0.1:9711),实验结束后已停止;CRL 与 OCSP 的耗时包含 JVM 首次类加载,不应当作网络延迟
    • 没有验证:真实互联网 CA 的 OCSP 响应器(含 nonce、stapling)、OCSP Must-Staple、TLS 握手里的 OCSP stapling(见 SSLSession 相关篇)、间接 CRL 与 delta CRL、CRL 条目的 certificateHold / removeFromCRL 语义、PKIXRevocationChecker 的 ONLY_END_ENTITY 与 jdk.security.certpath.ocspNonce 选项、响应器返回 unknown 或签名无效时的行为、大规模并发验证
    京ICP备2026067502号-1京公网安备11010502063487号