我目前正在尝试通过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];
}
}
您不清楚您的代码是客户端还是服务器,所以我都回答了,尽管这仅对服务器很重要。
尽管javadoc不是特定的,但X509TM.getAcceptedIssuers
不是用来决定是否信任已接收的证书或链。仅由checkServerTrusted
客户端或checkClientTrusted
服务器来完成。
的值getAcceptedIssuers
仅用于并影响两件事:
在服务器中(仅)(如果启用了客户端身份验证(通过调用needClientAuth(true)
或wantClientAuth(true)
)),则使用其元素中的使用者名称在服务器的CertificateRequest
message中创建CA列表。如果收到,则不必与将用作客户端证书链的信任锚的CA列表相同。事实上,的TrustManager实际上并不需要使用信任锚或连休息的列表标准验证算法 -尽管如果你的“代理”是标准的X509[Extended]TrustManager
,它使用的标准CertPathValidator
是做。但是,如果您告诉客户使用某些CA的证书,然后不接受来自这些CA的有效证书链,则您可能会有不满意的客户,他们可能会追随您。各种重的,尖锐的和/或其他不愉快的物体。
在没有 “ CA”(长度为0的数组)的特定情况下,客户端可以从其选择的任何CA发送证书,服务器仅根据接受证书checkClientTrusted
。
为了完整起见,RFC为客户端定义了扩展,以指定客户端希望服务器证书使用的CA,但是我不知道任何支持此扩展的实现,而Java / JSSE绝对不支持,因此在实践中服务器要么只有一个证书(每个算法),要么基于SNI选择(没有其他选择),并且如果客户端不信任该证书,那就太糟糕了。
如果您具有有效的算法约束(如今,即使您未明确设置某些约束,通常也默认情况下会执行),但如果链中的最后一个证书(推定锚)位于getAcceptedIssuers
,假定是(实际)锚点。换句话说,如果证书是信任锚,那么即使它使用的算法不符合当前标准(例如MD5或小于1024的RSA),也可能是用户决定信任它。
将证书放在信任库中或以其他方式使其成为锚点的人实际上是否正确地评估了其安全性,是Java不会尝试回答的另一个问题。尽管我敢肯定有人会很乐意尝试,但是即使Stackexchange也可能无法做到这一点。(我不承诺是否会成为其中之一。)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句