java - 实现 X509TrustManager

标签 java ssl x509trustmanager

我目前正在尝试通过 Java 中的 SSL/TLS 通过 Internet 传输数据,我希望双方都对自己进行身份验证。我自己实现了 KeyManager 来加载 key 对并向对方出示适当的证书。

现在,我正在尝试检查证书,我正在通过实现我自己的 TrustManager 来做到这一点(双方都持有另一方的证书,一切都是自签名的)。然而,getAcceptedIssuers 并没有像我希望的那样工作,因为即使我没有返回,连接仍然可以毫无问题地建立。

为什么证书没有被拒绝?

protected static class SelectingTrustManager implements X509TrustManager{
    final X509TrustManager delegate;

    private String[] trustedAliases;
    private final KeyStore keystore;

    public SelectingTrustManager(X509TrustManager delegate, KeyStore keystore, String[] trustedAliases) {
        this.trustedAliases = trustedAliases;
        this.keystore = keystore;
        this.delegate = delegate;
    }

    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException{
        delegate.checkClientTrusted(chain, authType);
    }

    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException{
        delegate.checkServerTrusted(chain, authType);
    }

    public X509Certificate[] getAcceptedIssuers(){
        return new X509Certificate[0];
    }

}

最佳答案

你不清楚你的代码是客户端还是服务器,所以我都回答了​​,尽管它只对服务器很重要。

尽管 javadoc 不是特定的,X509TM.getAcceptedIssuers 不用于决定是否信任收到的证书或链;这仅由客户端中的 checkServerTrusted 或服务器中的 checkClientTrusted 完成。

getAcceptedIssuers 的值仅用于并影响两件事:

  • 在服务器中,(仅)如果启用了客户端身份验证(通过调用 needClientAuth(true)wantClientAuth(true)),其元素中的主题名称是用于在 server's CertificateRequest message 中创建 CA 列表.如果收到,这不会强制与将用作客户端证书链的信任 anchor 的 CA 列表相同;事实上,trustmanager 实际上不需要使用信任 anchor 列表,甚至不需要 standard validation algorithm 的其余部分。 -- 虽然如果您的“委托(delegate)”是使用标准 CertPathValidator 的标准 X509[Extended]TrustManager 。但是,如果您告诉客户使用来自某些 CA 的证书,然后不接受来自这些 CA 的有效证书链,您可能会有不满意的客户,他们可能会来找您各种重的、尖锐的和/或其他不愉快的物体。

没有“CA”的特定情况下(长度为 0 的数组,如您所见),客户端可以从它选择的任何 CA 发送证书,并且服务器将接受它取决于仅在 checkClientTrusted 上。

为了完整性,请注意 RFC 为客户端定义了一个扩展,以指定它希望服务器证书使用哪些 CA,但我不知道有任何实现支持此扩展,而 Java/JSSE 绝对不支持,因此在实践中,服务器要么只有一个证书(每个算法),要么基于 SNI(仅此而已)进行选择,如果客户端不信任该证书,那就太糟糕了。

  • 如果您有有效的算法约束(现在您通常会默认执行,即使您没有明确设置)它们不会在链中的最后一个证书(假定的 anchor )上强制执行) 如果它在 getAcceptedIssuers 返回的证书中,则假定为(实际) anchor 。换句话说,如果证书是信任 anchor ,那么即使它可能使用不符合当前标准的算法(例如 MD5 或小于 1024 的 RSA),用户也可能决定信任它。

将证书放入信任库或以其他方式使其成为 anchor 的人是否真正正确地评估了其安全性是 Java 不会尝试回答的另一个问题。即使是 Stackexchange 也可能无法做到这一点,尽管我相信这里会有人乐于尝试。 (我不 promise 我是否会成为他们中的一员。)

关于java - 实现 X509TrustManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52487286/

相关文章:

java - 在X509TrustManager中,方法 "getAcceptedIssuers"有什么用?

java - Spring Data JPA/OpenJPA : Is there an equivalent to SQL ! =-运算符

java - Android View.getDrawingCache() 抛出 CalledFromWrongThreadException

java - 如何下载jaotc?

c# - 以不会成为 "God object"的方式设计类

google-maps - 通过 SSL 的 Google map 选项

php - fsockopen() 无法连接到 ssl

Java JDBC 无法使用 SSL 连接到 Oracle 数据库

java - 在 java 中抑制 SSL 证书验证会导致 502 无法连接。与 curl(使用 -k 选项)和 Postman(禁用 SSL)完美配合)

java - OkHttp3 中的 SSLSocketFactory 和 TrustManager 冗余