javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates does not conform to algorithm constraints解决方案

浏览: 2533

问题来源

用java开发爬虫程序时,我使用了webmagic框架,该框架可绕过部分https网站的证书,但对于某些尤其是银行类的网站,就遇到了这样的错误信息:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates does not conform to algorithm constraints”。

于是在网上一阵搜,都说出现该异常的原因是在JDK中做了限制。

解决方案

1.修改jdk文件

找到该文件:$JAVA_HOME/jre/lib/security/java.security

把其中的两行配置项:

jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024

jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768

改成:

jdk.certpath.disabledAlgorithms=,

jdk.tls.disabledAlgorithms=,

或者直接注释掉:

#jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024

#jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768

我照着改了,没有效果,依然报“Certificates does not conform to algorithm constraints”这个错误。

不过,就算改了有效果,貌似也不能随便改jdk的文件吧。

所以又找了第二种方案。

2.继承抽象类X509ExtendedTrustManager

https://stackoverflow.com/questions/14149545/java-security-cert-certificateexception-certificates-does-not-conform-to-algori

上面提到了

Check if you have a custom trust manager implementing the older X509TrustManager interface. JDK 7+ is supposed to be compatible with this interface, however based on my investigation when the trust manager implements X509TrustManager rather than the newer X509ExtendedTrustManager(docs), the JDK uses its own wrapper (AbstractTrustManagerWrapper) and somehow bypasses the internal fix for this issue.

据说在jdk1.7这个问题其实已经修补了(我使用的是jdk1.8仍然有这个问题),

但是如果我们自定义一个TrustManager类,实现X509TrustManager这个接口,而不是继承 X509ExtendedTrustManager 这个抽象类,那么jdk底层会使用AbstractTrustManagerWrapper这个类来包裹实现X509TrustManager接口的类,当使用这个wrapper的时候,一定程度上有时候会绕过已经被修复的问题,导致Certificates does not conform to algorithm constraints会再度复现。

所以解决方案就算应该自定义的TrustManager类继承抽象类:X509ExtendedTrustManager,则SSLContextImpl就会使用我们自己的TrustManager来验证证书算法,而我们这个类所有的验证方法都是空方法(也就是不验证),那么自然也就不会抛异常了。

private SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
// 继承X509ExtendedTrustManager抽象类,用于绕过验证,不用修改里面的方法
TrustManager[] trustAllCerts = new TrustManager[]{
new X509ExtendedTrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}

@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}

@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}

@Override
public void checkClientTrusted(X509Certificate[] xcs, String string, Socket socket) throws CertificateException {

}

@Override
public void checkServerTrusted(X509Certificate[] xcs, String string, Socket socket) throws CertificateException {

}

@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) throws CertificateException {

}


@Override
public void checkServerTrusted(X509Certificate[] xcs, String string, SSLEngine ssle) throws CertificateException {

}

}
};

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());

return sc;
}

如此修改后,确实没有再出现以上这个异常了。

推荐 0
本文由 _缘君_ 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册