3

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

现在,我正在尝试检查证书,我正在通过实现我自己的 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];
    }

}
4

1 回答 1

2

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

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

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

  • 在服务器中,(仅)如果启用了客户端身份验证(通过调用needClientAuth(true)or wantClientAuth(true)),则其元素中的主题名称用于在服务器的CertificateRequestmessage中创建 CA 列表。这并不强制与将用作客户端证书链的信任锚的 CA 列表相同(如果收到的话);事实上,信任管理器实际上不需要使用信任锚列表,甚至不需要使用标准验证算法的其余部分——尽管如果你的“委托”是使用标准X509[Extended]TrustManager标准CertPathValidator 做。但是,如果您告诉客户使用来自某些 CA 的证书,然后不接受来自这些 CA 的有效证书链,您可能会有不满意的客户来追随您各种重的、尖锐的和/或其他令人不快的物体。

没有“CA”的特定情况下(长度为 0 的数组,正如您所拥有的),客户端可以从它选择的任何 CA 发送证书,服务器将仅根据checkClientTrusted.

为了完整起见,RFC 为客户端定义了一个扩展,以指定它希望服务器证书使用的 CA,但我不知道任何支持此扩展的实现,Java/JSSE 肯定不支持,所以在实践中服务器要么只有一个证书(每个算法),要么根据 SNI 进行选择(仅此而已),如果客户端不信任该证书太糟糕。

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

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

于 2018-09-25T01:32:33.437 回答