我目前正试图通过java中的SSL/TLS在互联网上传输数据,我希望双方都能验证自己的身份。我自己实现了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];
}
}发布于 2018-09-25 01:32:33
您不清楚您的代码是客户端还是服务器,所以我将两者都回答,尽管这对服务器非常重要。
尽管javadoc不是特定的,但X509TM.getAcceptedIssuers并不用于决定是信任接收到的证书还是信任链;这完全是由客户机中的checkServerTrusted或服务器中的checkClientTrusted完成的。
getAcceptedIssuers的值只用于并影响两件事:
needClientAuth(true)或wantClientAuth(true)),则使用其元素中的主题名称在消息中创建CA列表。如果收到客户证书链,这并不强制与用作客户证书链信任锚的CA列表相同;事实上,信任管理器实际上并不需要使用信任锚列表,甚至标准验证算法的其余部分--尽管您的‘委托’是使用标准CertPathValidator的标准CertPathValidator。但是,如果您告诉客户使用来自某些CA的证书,然后不接受来自这些CA的有效证书链,您可能会有不愉快的客户端,他们可能会带着各种沉重、尖锐和/或其他令人不快的对象来找您。在没有“CA”的特定情况下,客户机可以从它选择的任何CA发送一个证书,并且服务器将只根据checkClientTrusted接受它。
为了完整起见,RFCs为客户机定义了一个扩展,以指定它希望服务器证书使用什么CA(s),但我不知道有任何支持此扩展的实现,Java/JSSE肯定不支持,因此在实践中,服务器要么只有一个证书(每个算法),要么它基于SNI (其他任何东西)进行选择,如果客户端不信任该证书,则情况太糟。
getAcceptedIssuers返回的证书之一(假定是锚),则不会在链中的最后一个证书上强制执行这些约束,而这些证书被假定为(实际的)锚。换句话说,如果证书是信任锚,那么用户可能已经决定信任它,尽管它可能使用不符合当前标准的算法(如MD5,或小于1024的RSA )。将证书放入信任库或以其他方式使其成为锚的人实际上正确地评估了它的安全性,这是Java没有试图回答的另一个问题。即使是Stackexchange也可能无法做到这一点,尽管我确信这里会有人乐于尝试。(我不承诺是否会成为他们中的一员。)
https://stackoverflow.com/questions/52487286
复制相似问题