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

12
我遇到了一个奇怪的问题 - 一个供应商同时使用自签名客户端和服务器证书的TLS SSLv3。这在Java1.5和Java1.6中没有问题 - 只需将客户端证书和私钥导入密钥库,将服务器公共证书导入信任库即可。 一切正常运行。
然而,在Java7中,尽管使用相同的信任库,服务器证书仍无法被信任。我已经尝试过Windows和Red Hat,两者都使用Java7(1.7.03、04和05,x86和x64版本),但都没有成功。
我已经从头开始重新创建了密钥库/信任库,它们只包含这些证书。已设置适当的系统属性(javax.net.ssl.keyStore,javax.net.ssl.trustStore),关键是相同的代码和配置在JDK5/6中完美运行。
我很迷惑 - 我找不到任何额外检查的参考资料,但我认为证书位于信任库中应该意味着它是受信任的,而不管是否自签名。
感谢任何帮助。 Ads
异常跟踪:
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调试失败的部分是尝试验证服务器证书:

***
%% 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)

来自 Ypsilon 的问候,我们正在努力处理 :) - cat_baxter
也许这与http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7018897有关? - Pma
дҪ иғҪеҗҰеңЁдҪ зҡ„javaе‘Ҫд»ӨиЎҢдёӯж·»еҠ -Djavax.net.debug=all并еҸ‘еёғе®Ңж•ҙзҡ„ж—Ҙеҝ—з»“жһңпјҢе°Өе…¶жҳҜеҠ иҪҪдҝЎд»»е•Ҷеә—зҡ„йғЁеҲҶпјҹ - David Grant
我现在正在尝试解决这个问题。我调查了Java错误数据库,它说这个问题已经被修复了,但我不知道解决方案是什么。有人知道如何解决吗? - IcedDante
@adam-green,你能想办法解决这个问题吗?我们有点陷入同样的困境... - tavlima
3个回答

10
我实际上遇到了一个类似的问题,当使用Java 1.6时,Tomcat应用程序会信任信任库中的CA证书,而在使用Java 1.7时会拒绝它。在我的CA证书中添加了keyUsage后,问题得到解决(在阅读了一个错误报告JDK-7018897 : CertPath validation cannot handle self-signed cert with bad 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 密钥,并插入新的密钥。


请参阅RFC 5280RFC 6125,了解Java使用的规则。 - jww
2
这个解决方案在Windows环境下如何工作?我没有openssl.cnf文件。看了一下错误报告,我不确定修复方法是什么。我应该在Java中获取证书并在运行时进行修改吗?这似乎不是正确的解决方案... - IcedDante
更具体地说,我已经安装了openSSL,并从目标服务器下载了证书。但我不确定如何获取oldca.key文件。此外,我认为证书应该使用“crt”扩展名进行管理。你使用pem的原因是什么? - IcedDante

0
由于某些原因,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" -nodes
keytool -import -keystore clientkeystore -file cert.der -alias bip70.com -storepass changeit

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


0
我在处理JDK 1.7时也遇到过这种情况。 如果使用 -x509 选项调用 req 命令,则最好取消注释 keyUsage 行并在 v3_ca 部分重新生成 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证书来签署其他证书,请确保您还取消注释basicConstraints = CA:true并将值设置为true。


@IcedDante - 请参阅 Stack Overflow 上的 如何使用您的认证机构签署 OpenSSL 证书签名请求? - jww

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接