【问题标题】:Java7 Refusing to trust certificate in trust storeJava7拒绝信任信任库中的证书
【发布时间】:2024-01-16 05:40:01
【问题描述】:

我有一个奇怪的问题 - 供应商使用带有自签名客户端和服务器证书的 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 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 的问候,我们正在努力 :)
  • 您能否将-Djavax.net.debug=all 添加到您的java 命令行并发布完整的结果日志,尤其是在加载信任存储的位置?
  • 我现在正在尝试解决这个问题。我调查了 Java 错误数据库,它说这个问题已解决,但我看不出解决方案是什么。有谁知道如何克服它?
  • @adam-green,你能弄清楚如何解决这个问题吗?我们有点像在同一条船上......

标签: java ssl ssl-certificate


【解决方案1】:

由于某些原因,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

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

【讨论】:

    【解决方案2】:

    我实际上遇到了一个类似的问题,Tomcat 应用程序在使用 Java 1.6 时会信任信任库中的 ca 证书,而使用 Java 1.7 会拒绝它。将keyUsage 添加到我的 ca 证书后,它可以工作(阅读错误报告后,JDK-7018897 : CertPath validation cannot handle self-signed cert with bad KeyUsage)。

    我做了什么(Ubuntu 12.04 x64):

    1. 编辑 /etc/ssl/openssl.cnf 并取消注释 keyUsage 部分中的 v3_ca 行。
    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 使用的规则。
    • 此解决方案如何在 Windows 环境中工作?我没有 openssl.cnf 文件。查看错误报告,我不确定修复是什么。我是否应该在 Java 中获取证书并在运行时对其进行修改?似乎不是正确的解决方案...
    • 更具体地说...我已经安装了openSSL,我已经从目标服务器下载了证书。但我不确定如何获得 oldca.key 文件。另外,我认为证书是用“crt”扩展名管理的。您使用 pem 有什么原因吗?
    【解决方案3】:

    我在处理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 证书签署其他证书,请确保您还取消注释项目 basicConstraints = CA:true 并将值设置为 true

    【讨论】:

    最近更新 更多