Java中的证书路径发现

时间:2013-04-12 14:52:00

标签: java security https x509 pki

我尝试通过java内置功能(HttpURLConnection)建立https连接。但我得到了这个例外:

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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
...
...

我的证书链是:

Root certificate -> Intermediate certificate -> Web server certificate

使用的证书通过“路径发现”的含义是正确的。信任锚是根证书,它在我系统上的java密钥库中导入。中间证书不是......但是

  1. 中间证书由我信任的根签署 - 所以我也相信中间人。
  2. Web服务器证书使用中级证书签名,我相信(第1点)
  3. 所以验证必须成功通过?我搞错了吗?

    在某处,我读到了这个:

      

    浏览器可以进行自动发现,服务器到服务器则不行。

    但缺少此功能是非常基本的。有没有明确的方法auto-discovery

    * * 更新

    是的,这是问题,GPI。我很困惑,因为浏览器可以验证服务器证书但java应用程序不能。 这种行为的原因是:

    • 服务器只发送最终证书,而不是整个证书 链;
    • 证书最近被买了,并且是相对签名的 新的中间证书;
    • 浏览器具有相对最新的证书列表 包括中间证书;
    • java有相对不是最新的证书列表,和 中间证书不在里面。
    • 浏览器通过中间件验证最终证书 certificate java无法检查证书链,因为:1。 链没有发送; 2.最终证书的签名者( 中间人)不是信任锚。

    解决方案可能是:

    • 服务器返回整个证书链
    • 要在java信任库中添加的中间证书

2 个答案:

答案 0 :(得分:3)

我相信您已经检查了您的链,因此我们可以理所当然地认为 RootCert 已签名 IntermediateCert IntermediateCert 已签名 ServerCert ,具有有效的X500名称链接和所有...

那就是说,你的逻辑是有效的,信任 RootCert 就足够了,但是不要忘记为了建立一个路径,你的客户必须拥有全部路径中的证书。

在您的情况下,如果您仅信任根证书,则由服务器来通告证书链的其余部分(中间和最终)。如果没有人“给”HTTP客户端中间证书,那么客户端将失败,因为从 Root Server 而不知道 Intermediate 不是可能的。

通过使用-Djavax.net.debug=all选项启动客户端,您实际上可以看到服务器证书链是什么。如果链的长度为1,那么您的服务器只会通告最终证书,客户端无法猜测中间证书是否存在。

(也可以使用浏览器检查并要求查看服务器证书,但是您应该注意浏览器将显示信任锚的整个路径,因此如果您想要推断服务器链是什么,你必须从这条路径中移除浏览器的锚点。)

在生产服务上,您应该参考您的证书提供商的网站,以了解什么是根证书(它可能不是最高级别的证书)。这个有效的root应该是你的客户端的信任锚,并且任何服务器都应该至少通告链中的最后一个证书(路径中的最后一个证书,其公用名是服务器的DNS名称)。

答案 1 :(得分:0)

要通过Https连接,您需要使用HttpsURLConnection对象。您无法使用HttpURLConnection对象创建连接。

相关问题