Java7拒绝信任信任存储中的证书

我有一个奇怪的问题 – 供应商使用TLS SSLv3同时拥有自签名客户端和服务器证书。 这对Java1.5和Java1.6来说不是问题 – 只需将客户端证书和私钥导入密钥库,将服务器公共证书导入信任库即可。 一切正常。 但是,对于Java7,即使使用相同的信任库,服务器证书也无法信任。 我尝试使用Java7(1.7.03,04和05,x86和x64版本)的Windows和Red Hat都没有成功。

我从头开始重新创建密钥库/信任库,它们只包含这些证书。 已经设置了适当的系统属性(javax.net.ssl.keyStore,javax.net.ssl.trustStore),关键方面是完全相同的代码和配置在JDK5 / 6中完美运行。

我不知所措 – 我找不到任何对额外检查的引用,但我认为证书位于信任库中的事实应该意味着无论是否自签,它都是可信的。

任何帮助赞赏。 广告

exception跟踪:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1868) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1338) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:154) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868) at sun.security.ssl.Handshaker.process_record(Handshaker.java:804) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:998) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1294) at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:685) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:111) at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221) at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291) at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295) at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141) at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229) at com.alltria.ypsilon.testing.TestSSL.main(TestSSL.java:65) Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:350) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:249) at sun.security.validator.Validator.validate(Validator.java:260) at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1320) ... 13 more Caused by: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:208) at java.security.cert.CertPathValidator.validate(CertPathValidator.java:279) at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:345) ... 19 more Java Result: 1 

ssl调试失败的部分是尝试validation服务器证书:

 *** %% Invalidated: [Session-1, SSL_RSA_WITH_RC4_128_SHA] main, SEND SSLv3 ALERT: fatal, description = certificate_unknown main, WRITE: SSLv3 Alert, length = 2 [Raw write]: length = 7 0000: 15 03 00 00 02 02 2E ....... main, called closeSocket() main, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors main, called close() main, called closeInternal(true) 

我实际上有一个类似的问题,在使用Java 1.6时,Tomcat应用程序会信任信任库中的ca证书,并使用java 1.7拒绝它。 将keyUsage添加到我的ca证书后,它可以正常工作(在阅读错误报告后, JDK-7018897:CertPathvalidation无法处理带有错误KeyUsage的自签名证书 )。

我做了什么(Ubuntu 12.04 x64):

  1. 编辑/etc/ssl/openssl.cnf并取消注释v3_ca部分中的keyUsage行。
  2. 使用以下命令生成包含keyUsage旧ca证书:

     openssl x509 -in oldca.pem -clrext -signkey oldca.key -extfile /etc/ssl/openssl.cnf -extensions v3_ca -out newca.pem 
  3. 从信任库中删除旧的CA密钥并插入新的CA密钥。

在处理JDK 1.7时我也遇到过这种情况。 如果使用-x509选项调用req命令,最好取消注释v3_ca部分中的keyUsage行并再次生成CA(参见http://wwwneu.secit.at/web/documentation/openssl/openssl_cnf.html )

 openssl req -new -x509 -days 3650 -keyout ca.key -out ca.crt -config openssl.cnf -extensions v3_ca -batch 

如果您使用生成的CA证书签署其他证书,请确保您还取消注释itemConstraints = CA:true并将值设置为true

由于某些原因,Java 8不接受自签名证书,甚至添加到其cacerts商店。

我的解决方法是创建一个自定义密钥库:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -subj "/C=MA/ST=ByExample/L=Test/O=Chapter3/OU=Org/CN=bip70.com" -node s

 keytool -import -keystore clientkeystore -file cert.der -alias bip70.com -storepass changeit 

然后在我的IDE中使用它作为jvm参数: -Djavax.net.ssl.trustStore=clientkeystore