Java 7(充当客户端)使用在Java 6中工作的密钥库和信任库的SSL握手失败 [英] Java 7 (acting as client) SSL handshake failure with keystore and truststore that worked in Java 6

查看:440
本文介绍了Java 7(充当客户端)使用在Java 6中工作的密钥库和信任库的SSL握手失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在进行JBoss AS 5.1到7.4以及Java 6到7的迁移,并且握手失败。

I'm doing a JBoss AS 5.1 to 7.4, and Java 6 to 7 migration, and get a handshake failure.

密钥库和信任库是我们的已经成功使用Java 6。

The keystore and truststore are the ones we have been using successfully for ages with Java 6.

我已经编写了一些测试来缩小问题范围,它绝对不是JBoss而是Java 7。

I've written some tests to narrow the problem down, it's definitely not JBoss but rather Java 7.

启用SSL日志后,我明白了:

With SSL logging turned on, I get this:

17:44:30,041 INFO  [stdout] (http-/192.168.147.20:8080-120) %% Invalidated:  [Session-2, SSL_RSA_WITH_RC4_128_SHA]
17:44:30,041 INFO  [stdout] (http-/192.168.147.20:8080-120) http-/192.168.147.20:8080-120, SEND TLSv1 ALERT:  fatal, description = certificate_unknown
17:44:30,041 INFO  [stdout] (http-/192.168.147.20:8080-120) http-/192.168.147.20:8080-120, WRITE: TLSv1 Alert, length = 2
17:44:30,041 INFO  [stdout] (http-/192.168.147.20:8080-120) http-/192.168.147.20:8080-120, called closeSocket()
17:44:30,041 INFO  [stdout] (http-/192.168.147.20:8080-120) http-/192.168.147.20:8080-120, 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
17:44:30,041 INFO  [stdout] (http-/192.168.147.20:8080-120) http-/192.168.147.20:8080-120, called close()
17:44:30,042 INFO  [stdout] (http-/192.168.147.20:8080-120) http-/192.168.147.20:8080-120, called closeInternal(true)

有一些线程涉及这个(或类似的)问题,人们建议重新创建具有不同参数的证书或信任商店。我宁愿不走这条路,因为我最近没有成功,试图为同一个webservice的不同帐户创建更多这样的密钥库和信任库。

There are some threads touching upon this (or a similar) problem, where people are suggesting to recreate certs or truststores with different params. I'd rather not go down this route, since I've recently without success tried to create more such keystores and truststores for different accounts of the same webservice.

由于我们一直在使用Java 6生产这些旧的(密钥库和信任库),我想尽可能保留它们。

Since we have been using these old (keystore and truststore) in production with Java 6, I'd like to keep them if at all possible.

看来问题可能是由于Java 7在检查信任库证书链时更紧张?

It appears the problem may be caused by Java 7 being more tight regarding the checking of truststore certificate chain?

是否有可能设置一些标志来放松检查,使其表现得像Java 6?

Is it possible to set some flags to relax the checking, make it behave like Java 6?

我不是100%肯定的事情是如何解释失败信息:我认为它告诉我它是我的机器(不是删除服务器),不满意远程机器是安全的。这是正确的吗?

A thing I'm not 100% sure about is how to interpret the failure message: I think it's telling me that it's my machine (not the remove server), which isn't satisfied that the remote machine is safe. Is that correct?

任何帮助/想法都赞赏!

Any help/ideas appreciated!

========== ================================================

==========================================================

如建议的那样,在访问WS URL时从firefox导出的PEM(带链)添加到信任库。这不会使它握手,但会稍微改变失败。

As suggested, have added PEM (with chain), exported from firefox when accessing the WS URL, to the truststore. This doesn't make it handshake, but slightly changes the failure.

***
%% Invalidated:  [Session-1, SSL_RSA_WITH_RC4_128_SHA]
main, SEND TLSv1 ALERT:  fatal, description = certificate_unknown
main, WRITE: TLSv1 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 01 00 02 02 2E                               .......
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1884)
    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:1341)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153)
    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:1016)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)

====================== ========================================

==============================================================

另外,正如其他线程所建议的,我编写了另一个使用不验证证书cha的TrustManager的测试ins,并用我原来的信任库运行它。

Also, as suggested in other threads, I've written another test that uses a TrustManager that does not validate certificate chains, and ran this with my original truststore.

这个测试能够连接,从而表明我的机器验证远程机器是唯一的问题,那个我的密钥库很好。

This test is able to connect, and thus shows that my machine's validating of the remote machine is the only problem, and that my keystore is fine.

然而,我不能将这种方法用于我们的实际web服务客户端,因为它使用Sun RPC lib,并且连接发生在他们的内部深处代码,所以我无法触摸它。

However, I can't use this approach for our actual webservice client, since that uses the Sun RPC lib, and connecting happens somewhere deep inside their code, so I can't touch it.

推荐答案

首先,是的,异常说你的机器中的Java SSL模块没有不相信从服务器收到的身份证明(证书)。

First, yes, the exception says the Java SSL module in your machine doesn't trust the proof of identity (certificate) received from the server.

是的,Java 7可以进行更严格的检查。可能会有更多,但我确定的是,它不允许子证书的有效期在父/ CA证书之后结束(或在之前开始,但在实践中不会发生)。请参阅 PKIX路径不与Windows环境中的任何信任锚错误链接,这表示它是一个错误并将被修复。

Yes, Java 7 does stricter checking. There may be more, but the one I'm sure of is that it doesn't allow the validity period of a child cert to end after the parent/CA cert (or begin before, but in practice that doesn't happen). See PKIX Path does not chain with any of the trust anchors error in Windows Environment which says it is a bug and will be fixed.

要检查:如果服务器是网络服务器,您可以使用浏览器访问任何(无害的)页面,并使用它来查看证书链。否则,运行 openssl s_client -connect $ host:443 -showcerts 并在连接后输入EOF(Unix ^ D,Windows ^ Z),然后将每个 ---- BEGIN CERT ... ----- END CERT ... 阻止在另一个文件中并运行 openssl x509 -noout -subject -issuer -startdate -enddate 按顺序排列。

To check: if the server is a webserver, you could access any (harmless) page with a browser and use that to look at the cert chain. Otherwise, run openssl s_client -connect $host:443 -showcerts and once it connects enter EOF (Unix ^D, Windows ^Z), then put each ----BEGIN CERT... to -----END CERT... block in a different file and run openssl x509 -noout -subject -issuer -startdate -enddate on each in order.

要修复:如果这是问题,似乎没有办法直接关闭它,除非关闭所有证书检查(因此失败) SSL的一些安全性,但是将服务器实体证书添加到您的信任库应该可以工作,因为Java不会验证链。 (您不需要删除已经存在的内容,只需使用尚未使用的别名。)祝您好运。

To fix: if this is the problem, there doesn't seem to be any way to turn it off directly, except by turning off all cert checking (and thus losing some of the security of SSL), but adding the server entity cert to your truststore should work because then Java doesn't verify the chain. (You don't need to remove what's already there, just use an alias that isn't already in use.) Good luck.

这篇关于Java 7(充当客户端)使用在Java 6中工作的密钥库和信任库的SSL握手失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆