简体   繁体   English

实现 X509TrustManager

[英]Implementing X509TrustManager

I'm currently trying to transfer data over the internet via SSL/TLS in java and I want both parties to authenticate themselves.我目前正在尝试通过 Java 中的 SSL/TLS 通过互联网传输数据,我希望双方都进行身份验证。 I have implemented the KeyManager myself to load the key pair and present the other party the appropriate certificate.我自己实现了 KeyManager 来加载密钥对并向对方提供适当的证书。

Now, I'm trying to check the certificate and I'm doing that by implementing my own TrustManager (both parties hold the cert of the other party, everything is self-signed).现在,我正在尝试检查证书,我正在通过实现我自己的 TrustManager 来做到这一点(双方都持有另一方的证书,一切都是自签名的)。 However, getAcceptedIssuers doesn't work like I want it to, because even when I return none the connection still gets established without problem.但是, getAcceptedIssuers 并没有像我希望的那样工作,因为即使我没有返回任何连接,连接仍然可以毫无问题地建立。

Why doesn't the certificate get refused?为什么证书没有被拒绝?

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];
    }

}

You aren't clear if your code is client or server, so I answer both, although it pretty much matters only for server.你不清楚你的代码是客户端还是服务器,所以我回答了两者,尽管它只对服务器很重要。

Although the javadoc isn't specific, X509TM.getAcceptedIssuers is NOT used to decide whether to trust a received cert or chain;尽管 javadoc 不是特定的,但X509TM.getAcceptedIssuers不用于决定是否信任收到的证书或链; that is done solely by checkServerTrusted in the client or checkClientTrusted in the server.这是由单独完成checkServerTrusted在客户端或checkClientTrusted在服务器中。

The value of getAcceptedIssuers is used for, and affects, only two things: getAcceptedIssuers的值仅用于并影响两件事:

  • in the server, (only) if client auth is enabled (by calling needClientAuth(true) or wantClientAuth(true) ), the Subject names from its elements are used to create the CA list in the server's CertificateRequest message .在服务器中,(仅)如果启用了客户端身份验证(通过调用needClientAuth(true)wantClientAuth(true) ),则其元素中的主题名称用于在服务器的CertificateRequest消息中创建 CA 列表。 This is not forced to be the same as the list of CAs that will be used as trust anchors for the client cert chain, if one is received;如果收到,这不会强制与将用作客户端证书链的信任锚的 CA 列表相同; in fact, the trustmanager isn't actually required to use a list of trust anchors or even the rest of the standard validation algorithm -- although if your 'delegate' is the standard X509[Extended]TrustManager which uses the standard CertPathValidator that does.事实上,的TrustManager实际上并不需要使用信任锚或连休息的列表标准验证算法-尽管如果你的“代理”是标准的X509[Extended]TrustManager它采用标准CertPathValidator 做。 However, if you tell client(s) to use cert(s) from certain CAs, and then don't accept valid cert chain(s) from those CAs, you will likely have unhappy client(s) who may come after you with various heavy, sharp and/or otherwise unpleasant objects.但是,如果您告诉客户使用来自某些 CA 的证书,然后不接受来自这些 CA 的有效证书链,您可能会有不满意的客户,他们可能会跟随您各种沉重、尖锐和/或其他令人不快的物体。

    In the specific case of no 'CAs' (an array of 0 length, as you have), the client can send a cert from any CA it chooses, and the server will accept it depending only on checkClientTrusted .没有“CA”(长度为 0 的数组,如您所拥有的)的特定情况下,客户端可以从它选择的任何 CA 发送证书,并且服务器将仅根据checkClientTrusted接受它。

    For completeness note the RFCs define an extension for the client to specify what CA(s) it wants the server cert to use, but I don't know any implementation that supports this extension and Java/JSSE definitely doesn't, so in practice the server either has only one cert (per algorithm), or it selects based on SNI (and nothing else), and if that cert isn't trusted by the client too bad.为了完整起见,RFC 为客户端定义了一个扩展,以指定它希望服务器证书使用的 CA,但我不知道支持此扩展的任何实现,Java/JSSE 绝对不支持,因此在实践中服务器要么只有一个证书(每个算法),要么它基于 SNI(没有其他任何东西)进行选择,如果该证书不被客户端信任太糟糕了。

  • if you have algorithm constraints in effect (and nowadays you usually do by default even if you don't explicitly set some) they are not enforced on the last cert in a chain (the putative anchor) if it is among the certs returned by getAcceptedIssuers , which are presumed to be (actual) anchors.如果你有算法约束(现在你通常默认情况下即使你没有明确设置一些)如果它在getAcceptedIssuers返回的证书中,它们就不会在链中的最后一个证书(假定的锚点)上强制执行,它们被假定为(实际)锚点。 In other words if a cert is a trust anchor presumably the user has decided to trust it even though it may use algorithms that do not meet current standards (like MD5, or RSA smaller than 1024).换句话说,如果证书是信任锚,用户可能已经决定信任它,即使它可能使用不符合当前标准的算法(如 MD5 或小于 1024 的 RSA)。

    Whether the person who put the cert in a truststore or otherwise made it an anchor actually evaluated its security correctly is a different question that Java doesn't try to answer.将证书放入信任库或以其他方式使其成为锚点的人是否实际正确评估了其安全性是 Java 不试图回答的另一个问题。 Even Stackexchange may not be able to do that, although I'm sure there will be people here glad to try.即使是 Stackexchange 也可能无法做到这一点,尽管我相信这里会有人乐于尝试。 (I make no commitment whether I will be one of them.) (我不承诺我是否会成为其中之一。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM