【问题标题】:Java SSL Certificate Revocation CheckingJava SSL 证书吊销检查
【发布时间】:2016-11-13 01:35:51
【问题描述】:

我目前正在使用 SSL 编写网络 TCP 服务器。在生产中,我们最终会要求客户端使用证书进行身份验证。

为了在紧急情况下撤销证书,我们还想建立一个 CRL。

我的问题是:Java 是开箱即用地检查 CRL(如果随证书一起提供)还是我需要手动实施此类检查?

为了测试,我准备了一个带有 CRL 集的证书,但 Java 似乎没有尝试验证它(我将它放到本地 Web 服务器中,并且无法访问)。

我只找到了 com.sun.net.ssl.checkRevocation=true VM 选项,但显然它没有查询 CRL。设置为 java.security.debug=certpath 的 VM 调试也不会生成任何输出...

Java 似乎在其子系统中有相关的类(例如 java.security.cert.X509CRLSelector),但显然它并没有发挥作用。

编辑:删除过时的 Dropbox 链接

【问题讨论】:

标签: java ssl certificate-revocation


【解决方案1】:

我想出了如何在 SSLContext 中启用 CRL 检查,而无需按照 cmets 中的建议实施自定义验证器。

主要是关于使用撤销检查器正确初始化 SSLContext 的 TrustManagers,只有几行,没有自定义检查逻辑,现在自动检查 CRL 以及验证路径。

这是一个sn-p...

KeyStore ts = KeyStore.getInstance("JKS");
FileInputStream tfis = new FileInputStream(trustStorePath);
ts.load(tfis, trustStorePass.toCharArray());

KeyManagerFactory kmf =  KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

// initialize certification path checking for the offered certificates and revocation checks against CLRs
CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
rc.setOptions(EnumSet.of(
    PKIXRevocationChecker.Option.PREFER_CRLS, // prefer CLR over OCSP
    PKIXRevocationChecker.Option.ONLY_END_ENTITY, 
PKIXRevocationChecker.Option.NO_FALLBACK)); // don't fall back to OCSP checking

PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(ts, new X509CertSelector());
pkixParams.addCertPathChecker(rc);

tmf.init( new CertPathTrustManagerParameters(pkixParams) );
// init KeyManagerFactory
kmf.init(...)

SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers), tmf.getTrustManagers(), null);

这基本上完成了我的应用程序所需的工作,检查颁发给客户的证书是否在我们的 CRL 中被撤销。只接受检查最终实体并允许 CRL 检查失败,因为它是我们所有的基础设施。

【讨论】:

  • 嘿,java 1.7有类似的解决方案吗?
  • @mdavid:抱歉,我多次拒绝给你这个答案,但也许你应该试试 Java 8(发布 3 年后?)。安全堆栈有大量改进:oracle.com/technetwork/java/javase/8-whats-new-2157071.html _PKIXRevocationChecker _ 甚至在更改日志中提到,我认为在 1.7 中没有用于验证证书的开箱即用解决方案。
  • 嗨@DoNuT,它是否负责从远程位置获取CRL(在证书中提供)并将其缓存到下一次更新时间?然后再次获取新的 CRL?提前致谢。
  • @ramtech:我还没有检查实现,但据我使用 SOFT_FAIL 选项(可能在我的场景中不可用)的测试中知道,它不会缓存命中 CRL 位置每次。
  • 好的 nvm 它会为每个请求克隆,所以看起来很丑但线程安全
【解决方案2】:

OCSP 适合您吗?

下面的代码为我启用了 OCSP:

// for debugging:
System.setProperty("javax.net.debug", "all");
System.setProperty("java.security.debug", "all");

System.setProperty("com.sun.net.ssl.checkRevocation", "true");
Security.setProperty("ocsp.enable", "true");

由于以下错误在 CRL 上失败:How to check revocation status of X509Certificate chain using JAVA?

【讨论】:

    【解决方案3】:

    请注意,禁用吊销检查是一种不好的安全做法。你可以这样做,但要确保你知道风险!

    @DoNuTcurrently accepted answer 通过设置 PKIXRevocationChecker.Option.SOFT_FAIL 工作,即使撤销检查失败,验证器也不会抛出异常。以下答案完全禁用吊销检查,因此如果您根本不需要验证,它会更快。这是因为执行吊销检查需要联系 CRL 分发点或 OCSP 服务器,如果您不想这样做,则无需付出代价。

    您可以简单地在PKIXBuilderParameters 类型的对象上使用setRevocationEnabled(false)

    // Initialize "anchors" to trusted certificates
    // Initialize "selector" to the certificate you want to validate
    PKIXBuilderParameters pbParams = new PKIXBuilderParameters(anchors, selector);
    
    pbParams.setRevocationEnabled(false); // disable revocation check
    
    CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
    CertPathBuilderResult cpbResult = cpb.build(pbParams);
    
    CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
    CertPathValidatorResult result = cpv.validate(cpbResult.getCertPath(), pbParams);
    
    System.out.println(result);
    

    【讨论】:

    • 我不确定您是否完全得到了我想要在这里实现的目标?我确实想要撤销检查,你建议完全禁用它吗? SOFT_FAIL 对于我的带有自签名证书和内部 CRL 的用例是可以接受的(如果 CRL 暂时不可用,请不要破坏应用程序),但我已将其从示例中取出以避免人们将其粘贴到他们的代码中。
    • @DoNuT 如果SOFT_FAIL 有一个上限时间,那么temporarily 这个词就有意义了,恕我直言!
    • SSL/TLS 不需要 这是 Q 和 selfA(现在修改 BTW); JSSE 会自动执行setRevocationChecking(false),除非您设置了一个 sysprop——在 fishautumn 的新 A 中正确给出。
    【解决方案4】:

    首先,您可以在 jcontrol(从 1.8 开始)中配置的吊销检查仅适用于 appletWebStart 下载和签名者证书检查! 对于编程的 https 客户端,您可以使用上面提到的 PKIXRevocationChecker,但根据我的经验,Oracle 实现根本不支持 LDAP CDP 下载。 当我遇到这个问题时,我需要使用 CRL 实现完整的证书链检查,并在我的自定义 TrustManager 的 checkXXXX 函数后面立即从 LDAP 下载 CA 证书......

    【讨论】:

    • 你是对的,上面列出的VM选项没有效果。只要一个 SSLContext 分别使用底层的 TrustManagers,你应该避免添加一个 PKIXRevocationChecker 的方法,所以 Java HTTP 客户端和 Apache 框架。据我所知,它只支持 CRL 和 OSCP,LDAP 可能是一个不同的主题,但你总是可以增加复杂性。我手中有客户端和服务器的证书处理,所以我选择了最简单的方法,即 CRL。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-15
    • 2011-07-18
    • 2018-01-15
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多