Why am I getting "No issuer certificate for certificate in certification path found" error for a known and trusted certificate?

时间:2016-10-20 19:00:13

标签: java ssl https

I am trying to connect to a server with a Java Http client to make a web service call. If I turn net debugging on with the below code..

System.setProperty("javax.net.debug", "all");

I am seeing that certificates from Entrust seem to be added as trusted certificates. Among those added were the below...

 adding as trusted cert:
 Subject: CN=Entrust.net Certification Authority (2048), OU=(c)    1999   Entrust.net Limited, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), O=Entrust.net
 Issuer:  CN=Entrust.net Certification Authority (2048), OU=(c) 1999 Entrust.net Limited, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), O=Entrust.net
 Algorithm: RSA; Serial number: 0x3863def8
 Valid from Fri Dec 24 12:50:51 EST 1999 until Tue Jul 24 10:15:12 EDT 2029

It seems as if the server is using a cert from Entrust because I also see in the debug...

main, READ: TLSv1 Handshake, length = 2649
*** Certificate chain
chain [0] =   [0]         Version: 3
     SerialNumber: 1356119177
       IssuerDN: C=US,O=Entrust\, Inc.,OU=See www.entrust.net/legal-terms,OU=(c) 2012 Entrust\, Inc. - for authorized use only,CN=Entrust Certification Authority - L1K
       Start Date: Wed Jul 15 11:50:20 EDT 2015
       Final Date: Sun Jul 15 18:27:04 EDT 2018

And yet during the handshake process I get the below exception...

***
Caught: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 
PKIX path building failed: java.security.cert.CertPathBuilderException: 
No issuer certificate for certificate in certification path found.
main, SEND TLSv1 ALERT:  fatal, description = certificate_unknown

2 个答案:

答案 0 :(得分:0)

我通过创建一个接受服务器证书的信任管理器来解决这个问题,并指出我的Apache HttpClient使用该信任管理器......

 private class TrustAll implements X509TrustManager
{
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
{
}

public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
{
}

public X509Certificate[] getAcceptedIssuers()
{
    return new X509Certificate[0];
}

}

TrustManager[] trustArray = [new TrustAll()] as TrustManager[]
SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(null, trustArray, null);

// create an http client builder
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
 httpClientBuilder.setSslcontext(ctx)

 httpclient = httpClientBuilder.build();

答案 1 :(得分:0)

我能够通过将服务器证书添加到我的java客户端(jre的cacerts和jssecacerts)来解决这个问题。

如果我们以这种方式向java客户端添加证书,我们会要求我们的jre信任该服务器的证书。

echo | openssl s_client -showcerts -connect www.xyz.com:443 2>&1 |
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/cert.pem

#cacerts
keytool -import -alias certname -file /tmp/cert.pem -keystore
/usr/java/jdk1.8.0_45/jre/lib/security/cacerts -storepass changeit

#jssecacerts(Normally we remove this file)
keytool -import -alias certname -file /tmp/cert.pem -keystore
/usr/java/jdk1.8.0_45/jre/lib/security/jssecacerts -storepass changeit

如果通过应用程序服务器执行此客户端代码,请重新启动应用程序服务器

确保您在环境变量中有 openssl,keytool ,并更改您各自的JAVA_HOME位置。