在 OpenJDK 11 中启用 SSL 证书吊销检查

Posted

技术标签:

【中文标题】在 OpenJDK 11 中启用 SSL 证书吊销检查【英文标题】:Enable SSL certificate revocation checking in OpenJDK 11 【发布时间】:2019-08-15 17:32:15 【问题描述】:

在 Java 11 中是否有一些快速的“声明性”方式,而不是繁琐的手动实现来检查证书是否被吊销?

我尝试使用此答案中的属性: Check X509 certificate revocation status in Spring-Security before authenticating 使用此虚拟吊销证书:https://revoked.badssl.com 但代码始终接受证书。我是在做错什么,还是这些属性对于 Java 11 不再实际?如果是这样,我们还有其他选择吗?

下面是我的代码:

public static void validateOnCertificateRevocation(boolean check) 
    if (check) 
        System.setProperty("com.sun.net.ssl.checkRevocation", "true");
        System.setProperty("com.sun.security.enableCRLDP", "true");

        Security.setProperty("ocsp.enable", "true");
    

    try 
        new URL("https://revoked.badssl.com").openConnection().connect();
     catch (IOException e) 
        e.printStackTrace();
    

【问题讨论】:

【参考方案1】:

似乎必须在执行第一个请求之前设置这些选项。

因此,作为独立 Java 程序的以下代码会引发 CertPathValidatorException: Certificate has been revoked(在 Windows 上使用 OpenJDK 11.0.2 x64 测试):

public static void main(String[] args) 
    validateOnCertificateRevocation(true); // throws CertPathValidatorException

但是以下代码不会导致任何错误/异常:

public static void main(String[] args) 
    validateOnCertificateRevocation(false);
    validateOnCertificateRevocation(true); // nothing happens

您可以看到在处理第一个请求后更改选项无效。我假设这些选项是在一些证书验证相关类的static ... 块中处理的。

如果您仍想基于每个请求启用/禁用证书吊销检查,您可以通过实现您自己的使用 CertPathValidatorX509TrustManager 来实现(您可以通过 @987654329 启用/禁用证书吊销检查@。

或者,有一种解决方案可以全局启用证书吊销检查并显式处理 CertificateRevokedException:

private boolean checkOnCertificateRevocation;

@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException 
    try 
        getDefaultTrustManager().checkServerTrusted(certs, authType);
     catch (CertificateException e) 
        if (checkOnCertificateRevocation) 
            if (getRootCause(e) instanceof CertificateRevokedException) 
                throw e;
            
        
    

【讨论】:

谢谢!正如您所料,“com.sun.net.ssl.checkRevocation”属性实际上只在初始化“sun.security.validator.PKIXValidator”类中的静态字段“checkTLSRevocation”时被处理一次。因此,作为一种解决方法,我们可以始终启用此属性并根据客户端代码中的布尔标志捕获/重新抛出异常。但是也许存在一些更优雅的解决方案来启用/禁用每个请求中的撤销检查? 您可以实现自己的X509TrustManager,使用CertPathValidator 来验证证书。使用的PKIXParameters 类有一个名为setRevocationEnabled(boolen) 的方法,可以启用/禁用证书吊销检查。这应该适用于每个请求级别。 感谢您的帮助!然而,在多次尝试实现过于复杂的CertPathValidator 之后,它决定坚持“总是扔,需要时抓住”的原则。自定义 X509TrustManager 的最终代码现在看起来像 @Override public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException try getDefaultTrustManager().checkServerTrusted(certs, authType); catch (CertificateException e) if (checkOnCertificateRevocation) if (getRootCause(e) instanceof CertificateRevokedException) throw e; @Roman 我更新了我的答案,并包含了我们来自 cmets 的讨论。

以上是关于在 OpenJDK 11 中启用 SSL 证书吊销检查的主要内容,如果未能解决你的问题,请参考以下文章

启用自动管理签名时请求吊销证书

在 Ubuntu OpenJDK 7 上启用密码

为什么SSL证书要设有效期?

申请免费的ssl通配符证书

自己签发的证书与根内置的第三方机构(如天威诚信)颁发的证书有啥不同?存在啥风险?

使用 openjdk 1.8 的 Java SSL 通信握手失败