为什么我会收到握手失败的错误消息 (Java SSL)

11

我正在使用HTTPS连接到一个Web服务。我已经完成了我认为可以使它工作所需的一切工作,但最终我遇到了握手失败的问题。

我发现作为新用户,由于“垃圾邮件保护”,我不能发布超过2个链接-非常感谢stackoverflow……无论如何,这里有一个pastebin帖子的链接,其中包含所有拼写正确的链接……所以当我在这里写“link#1”时,它是对这些链接的引用:http://pastebin.com/y4zGNRC7

  • 我使用HttpClient(对服务URL进行GET)和通过CXF代理实际调用Web服务来验证了相同的行为
  • 我设置了密钥库和信任库-我尝试了“代码中”的方法(link#1)和设置系统属性-即System.setProperty(“javax.net.ssl.keyStore”,“mykeystore.jks”);
  • SSL调试打开(javax.net.debug = all)
  • SSL调试突出显示密钥库和信任库的内容(即看起来像java“知道它们”)-link#2
  • 似乎存在一些客户端-服务器通信,但然后因某种原因而崩溃link#3
  • 我成功地使用客户端和CA证书在浏览器(Chrome)中和使用openssl s_client连接到了服务器
  • wireshark显示java的客户端-服务器交互较少(link#4),例如与Chrome(link#5)相比

另一个奇怪的事情是,当我设置密钥库时和不设置时似乎得到了相同的行为(唯一的区别是当我这样做时,密钥库内容会打印在控制台中,但仅此而已)。

我尝试通过谷歌搜索来解决这个问题,我看到了许多类似的帖子在stackoverflow上,但都没有帮助。 我尝试更改协议版本(“TLSv1”,“SSLv3”,甚至是奇怪的v2 Hello)。 任何帮助将不胜感激-也许有些基本的东西我可能忽视了……我变得绝望了… 谢谢

我在 Fedora Core 15(64位) 上运行 Java 1.6 更新版30。


1
你能发布一个异常堆栈跟踪吗? - home
我发现作为新用户,由于“垃圾邮件保护”,我不能发布超过2个链接-感谢stackoverflow。如果您经常使用此网站,则会意识到SO的垃圾邮件保护措施是一件好事。 - Stephen C
1
说到链接,发布pastebin链接和类似的链接被认为是不好的做法,因为它们很快就会消失,使得问题对于未来的读者难以理解。 - Stephen C
这是堆栈跟踪 http://pastebin.com/dbXPYRmS - Jakub Hlavatý
是的,抱歉我有点激动,但我理解它如何帮助对抗垃圾邮件...... 外部链接在我看来是“不污染”问题过多细节的好方法.... 况且还有字符限制吧? Pastebin让您选择帖子的“到期日”......而“永不”似乎是一个不错的选择;-) 如果stackoverflow本身提供这样的功能就太好了。 - Jakub Hlavatý
显示剩余8条评论
3个回答

5
问题在于,虽然设置了密钥库和信任库,但Java决定不向服务器发送客户端证书。原因是服务器请求使用由RootCA机构签名的证书,而客户端证书是由SubCA机构签名的(由RootCA签发)。
最初,密钥库只包含客户端证书,而信任库则包含SubCA证书。我尝试将SubCA证书也添加到密钥库中,但Java忽略了它。
所以这解决了握手失败的谜团,但并没有解决我的问题。
我为此创建了一个单独的问题...哎呀 :-( 为什么Java在SSL握手期间不发送客户端证书?

4

我认为信任存储库不包含CA证书是最可能的问题。你可以使用Java keytool将站点证书导入到cacerts文件中,方法如下:

keytool -keystore pathtocacerts -import -trustcacerts -v -alias aliasName -file root.crt

默认的 cacerts 密钥库密码为 changeitcacerts 文件通常位于 jre/lib/security 目录下。


我非常确定信任存储库包含CA。当这样做不起作用时,我还将根CA证书导入到信任存储库中...但似乎没有帮助。 - Jakub Hlavatý
1
请注意,启用SSL调试后,信任存储库和密钥库的内容都会在控制台中打印出来。此外,客户端证书和CA证书(而不是根证书)就足以使其在浏览器中工作。 - Jakub Hlavatý
我尝试使用keytool检查存储的内容,一切似乎都没问题。我甚至尝试通过启动命令行选项设置两个存储(即“-Djavax.net.ssl.keyStore =”),但没有成功... - Jakub Hlavatý

2
您没有提供足够的信息,但我猜测您的客户端信任库配置不正确。信任库包含用于签署其他证书的受信任证书,并且必须包括服务器和客户端证书链的根证书。客户端密钥库包含客户端SSL证书和私钥。

谢谢你的回复,Greg。请告诉我还需要提供哪些信息。我尽可能详细地描述了问题,但我知道可能会漏掉一些东西。 正如我所写的,我设置了_truststore_和_keystore_。在日志中,我用X代替了实际的证书名称和其他内容,因为我不想在线上发布这些信息。keystore包含客户端证书和私钥。truststore包含颁发证书的CA证书和根CA证书。 堆栈跟踪似乎对此并没有太大帮助(我在上面的评论中发布了它)。 - Jakub Hlavatý
似乎客户端的密钥库已经被加载,但是客户端证书没有被呈现给服务器,这就是握手失败的原因。日志显示一个空的客户端证书链。但我不知道为什么会这样 :-( - Jakub Hlavatý

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