为什么我需要将中间 CA 证书添加到 JVM 的 cacerts 文件中?

信息安全 证书 公钥基础设施 爪哇
2021-08-18 04:39:05

我的公司使用自己的 PKI。我用来访问代码存储库的 Web 浏览器显示了一个证书链,如下所示:

Company Root CA
    Company Issuing CA Intranet Server
        Certificate to the code repository that I want to access

但是,当我尝试使用 Gradle 访问存储库时,我得到一个

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

错误。

Gradle 使用 JVM。我已导出“公司根 CA”证书,并使用以下命令将其添加到 JVM 的证书存储中:

"%JAVA_HOME%\bin\keytool.exe" -import -alias company_root_cacert -file "C:\path\to\company\root\cacert.cer" -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -storepass changeit

然而,这并没有解决问题。我还导出了“Company Issuing CA Intranet Server”证书,并使用以下命令将其添加到 JVM 的证书存储中:

"%JAVA_HOME%\bin\keytool.exe" -import -alias company_intermediate_cacert -file "C:\path\to\company\intermediate\cacert.cer" -keystore "%JAVA_HOME%\jre\lib\security\cacerts" -storepass changeit

这已经解决了这个问题。

我的问题是,为什么第二步是必要的?既然“Company Issuing CA Intranet Server”是由“Company Root CA”签名的,而且我在JVM信任的证书列表中有“Company Root CA”,为什么还要额外添加“Company Issuing CA Intranet Server” " 证书到 JVM 的证书存储区?

2个回答

您描述的问题通常发生在服务器仅发送其叶子证书并且没有将构建信任链所需的所有链证书添加到根 CA 的情况下。不幸的是,这是服务器的常见错误配置。

如果许多桌面浏览器已经从早期访问中知道丢失的链证书,或者如果叶证书包含 CA 颁发者在授权信息访问中的 URL,则可能会下载丢失的证书,从而解决此问题。但是这种行为通常仅限于桌面浏览器和其他工具,因为它们无法建立信任链而失败。

Oracle JRE 可以自动下载中间证书:

支持权威信息访问 (AIA) 扩展

提供对权威信息访问扩展的 caIssuers 访问方法的支持。出于兼容性考虑,默认情况下禁用它,可以通过将系统属性设置 com.sun.security.enableAIAcaIssuers为 value来启用它true

如果设置为 true,则 Sun 的 PKIX 实现CertPathBuilder使用证书的 AIA 扩展中的信息(除了 CertStores指定的)来查找颁发的 CA 证书,前提是它是 ldap、http 或 ftp 类型的 URI。

注意:根据您的网络和防火墙设置,可能还需要按照网络文档中的说明配置网络代理服务器。

(来源:Oracle,“Java PKI 程序员指南”。)