sun.security.validator.ValidatorException:PKIX 路径构建失败

Posted

技术标签:

【中文标题】sun.security.validator.ValidatorException:PKIX 路径构建失败【英文标题】:sun.security.validator.ValidatorException: PKIX path building failed 【发布时间】:2014-09-05 06:19:46 【问题描述】:

我已使用此命令创建了 CSR 请求:

openssl req -out certificatecsr.csr -new -newkey rsa:2048 -keyout certificatekey.key

在 CA 与我共享证书 (.cer) 文件之后。

现在我已经使用密钥将 .c​​er 文件转换为 .p12。

使用 CA 发送的 cer 和私钥创建 .p12 证书

C:\Java\jdk1.6.0_38\jre\bin>openssl pkcs12 -export -in C:\Users\asharma1\cert.cer -inkey certificatekey.key -out

certi.p12

创建 JKS 密钥库:

keytool -genkey -alias quid -keystore quid.jks

将 .p12 证书导入 jks 密钥库

C:\Java\jdk1.6.0_38\jre\bin>keytool -v -importkeystore -srckeystore C:\OpenSSL-Win64\bin\certi.p12 -srcstoretype PKCS12

-destkeystore quid.jks -deststoretype JKS

但是当我从我的 java 代码中引用这个 JKS 时,我收到了这个错误:

sun.security.provider.certpath.SunCertPathBuilderException: 无法找到请求目标的有效证书路径

我也将 cer 文件添加到 cacerts。但仍然出现相同的错误。

就 JAVA 代码而言,我引用此链接来引用我自己创建的密钥库:

http://jcalcote.wordpress.com/2010/06/22/managing-a-dynamic-java-trust-store/

public SSLContext getSSLContext(String tspath) 
        throws Exception 

      TrustManager[] trustManagers = new TrustManager[]  

        new ReloadableX509TrustManager(tspath) 
      ;
      SSLContext sslContext = SSLContext.getInstance("TLS");

      sslContext.init(null, trustManagers, null);

      return sslContext;

    

SSLContext sslContext=getSSLContext("C:\\Java\\jdk1.6.0_38\\jre\\bin\\quid.jks");
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
URL pickUrl = new URL(pickupLocation);
URLConnection urlConn = pickUrl.openConnection();
HttpsURLConnection httpsURLConn = (HttpsURLConnection)urlConn;
httpsURLConn.setSSLSocketFactory(socketFactory);
String encoding = urlConn.getContentEncoding();   
InputStream is = urlConn.getInputStream();    
InputStreamReader streamReader = new InputStreamReader(is, encoding != null
? encoding : "UTF-8");

请注意我没有使用任何服务器。我正在尝试仅通过 main 方法在编写的代码之上运行。

请告诉我需要做什么。 为什么我需要将我的 .cer 文件转换为 .p12 文件?

【问题讨论】:

这没有任何意义。您必须首先生成私钥。 然后是 CSR。然后签到。然后将其与私钥重新组合。 @EJP 命令openssl req -out certificatecsr.csr -new -newkey rsa:2048 -keyout certificatekey.key 根据文档here 创建一个新的证书请求和一个新的私钥 那么你究竟为什么要使用'keytool -genkey'? @EJP 这正是正在发生的事情。首先生成私钥和 csr,然后由 CA 签名,然后将其与私钥组合形成 .p12 密钥库。然后将其转换为 JKS 存储。 没有。 'keytool -genkey' 创建一个 new 密钥。请参阅文档。您的命令序列没有意义。 【参考方案1】:

我建议您将 CA 证书(或整个 CA 链和中间 CA)导入密钥库。

我认为 p12 导入得很好。我的建议是将链导入密钥库。至少这是错误消息所说的。

我认为:

链中的根 CA 不受信任,因此链构建失败或 链中的证书中没有 AIA 部分,因此无法获取到受信任的根 CA 的证书,因此链构建失败或 没有基于 AIA 获取证书,因为它没有在 java 中实现(我不是 java 程序员)所以链构建失败

您可以使用portecle 导入缺少的受信任 CA 证书(不是您在 .p12 或您从颁发 CA 收到的单独 .cer 文件中拥有的最终实体证书)。它比 keytool 更加用户友好。只需关注此guide。

【讨论】:

感谢您的回复,我已经使用 portecle 进行了检查。证书存在于 quid.jks 密钥库中。我已经检查了 quid.jks 中的 .cer 和 .p12 文件但是,当我尝试通过 portecle 导入受信任的证书(certi.p12)时,它显示错误“在 certi.p12 中找不到证书”,但适用于 . .cer 文件。我不确定根 CA 和中间 CA。需要检查什么?我猜导入证书相当于导入CA。【参考方案2】:

我建议您使用 *.der 格式而不是 .p12 格式。

以下是如何导入证书以修复以下错误的总体摘要:

尝试执行请求时出错。 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:PKIX 路径构建失败: sun.security.provider.certpath.SunCertPathBuilderException:无法 找到请求目标的有效认证路径

如何导入证书

    在浏览器中转到 URL,点击 HTTPS 证书链(URL 地址旁边的小锁符号)导出证书 点击“更多信息”>“安全”>“显示证书”>“详细信息”>“导出..”。 另存为.der 对需要导入的任何证书重复此操作 找到 $JAVA_HOME/jre/lib/security/cacerts

    使用以下命令将所有 *.der 文件导入 cacerts 文件:

    sudo keytool -import -alias mysitestaging -keystore $JAVA_HOME/jre/lib/security/cacerts -file staging.der
    sudo keytool -import -alias mysiteprod -keystore  $JAVA_HOME/jre/lib/security/cacerts -file prod.der
    sudo keytool -import -alias mysitedev -keystore  $JAVA_HOME/jre/lib/security/cacerts -file dev.der
    

    默认密钥库密码是“changeit”

    您可以查看您使用此显示证书指纹的命令所做的更改。

    keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts
    

    如果这不能解决问题,请尝试添加这些 java 选项作为参数:

    -Djavax.net.ssl.trustStore="$JAVA_HOME/jre/lib/security/cacerts"
    -Djavax.net.ssl.trustStorePassword="changeit"
    

【讨论】:

以上是关于sun.security.validator.ValidatorException:PKIX 路径构建失败的主要内容,如果未能解决你的问题,请参考以下文章