如何将 CA 证书添加到 cacerts 存储以便它按预期工作?

How to add CA certificate to cacerts store so that it works as expected?

更新:找到解决方案后,我将问题编辑得更清楚以供将来参考。

我从一家公司获得了公司(即不为人知的)CA 证书,该公司为我们提供了从 Java 调用的 Web 服务。我将此 CA 证书添加到默认的 cacerts 信任库 (keytool -import -file cert.cer -alias myca -keystore jre/lib/security/cacerts),但与该服务的连接仍然失败,并显示可怕的 "PKIX path building failed" 消息。我已经检查了终端服务器证书的颁发者字段与 CA 证书中的相同,并且有效日期也没有问题。

我不知道怎么解释。我可以想到以下原因,但我不知道哪个是正确的:

  1. 我注意到,当我也将终端服务器证书添加到信任库时,连接正常。也许 cacerts 的设计并不像我预期的那样工作(即所有由权威机构签署的证书都被认为是有效的),但我必须将所有终端服务器证书添加到信任库中,包括其颁发者的 CA 证书。
  2. 我必须以其他方式添加 CA 证书 - 通过不同的命令,添加到不同的文件等。
  3. 可能 CA 证书不正确,keytool 拒绝将其视为证书颁发机构。
  4. 可能由于其他原因 PKIX 路径构建失败。

如何调试这个问题才能找到答案?

详情:

信任库需要包含根证书(CA 的证书)。

我不确定 "the last one I'm the chain" 是不是你的意思,但是 CA 证书应该是服务器提供的证书链中的最后一个。

如果您的证书是由知名 CA 签署的,那么 CA 证书应该在信任库中,如果服务器的证书链设置正确,一切都应该正常工作。

如果您的证书是自签名证书,那么根证书将不会在信任库中,您必须添加它。

我遇到了与 "PKIX path building failed" 相同的问题,一次使用 Let's Encrypt 签名证书 Java 没有将 Let's encrypt CA 证书合并到其默认信任库中。

我的故事详细写在这里:http://blog.novoj.net/2016/02/29/how-to-make-apache-httpclient-trust-lets-encrypt-certificate-authority/

最后,我能够通过创建嵌入在我的应用程序中的内部信任库来使 Java 信任 "the end of the chain" 服务器证书,该信任库仅包含根 CA 证书(和备份证书)。

与在主 Java 信任库中导入证书相比,我更喜欢创建内部应用程序信任库,原因有两个:

  • 您不需要在安装过程中执行其他额外步骤来初始化全局信任库
  • 您将 "the trust" 限制为您的应用程序并且不影响同一 JVM 上的其他应用程序 运行(或者更好的是,您甚至可以将信任限制为您应用程序中客户端对象的某些实例如果需要)

也许我遇到的情况与您面临的情况不同,所以如果我不明白这一点,请给我投反对票。

感谢@pedrofb 的评论,我发现 PKIX 路径失败的原因很简单,我得到的 CA 证书不是签署最终证书的 CA。使事情变得如此复杂的是给我 CA 证书的公司的巨大无能,它显然有两个 CA,其描述几乎相同(cn、o、st、c),仅 SN 不同,并且都颁发了相同的通配符证书。直到我变得超级偏执并比较了SN之后,我才明白问题所在。