Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
676 views
in Technique[技术] by (71.8m points)

ssl - PKIX Path does not chain with any of the trust anchors error in Windows Environment

I am a bit of an idiot to how SSL and Webservices work at the fine-grained level. I am developing a system that calls several web services, some with secured URLs and others that are not with little problem. Currently, however, I am doing an integration with Endicia's LabelServer Web API. The webservice is used to calculate and print postage.

The test URL and WSDL is at: https://www.envmgr.com/LabelService/EwsLabelService.asmx

I used wsimport to create and setup a Java client for connecting to this webservice but when I try to all it I get the error

PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors

This error is documented here: Java7 Refusing to trust certificate in trust store

in which it's discussed how Java 7 forces an error with self-signed certificates with "bad" keyusage. Bad in this situation is defined as not containing keyCertSign. The webservice does work with Java 6. I can believe this situation might apply to this certificate since it's only being used as a test server, but I don't know how to verify that.

There's a bug report on it that is solved (http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7018897), but I'm not sure how any of this translates to fixing the problem for a Windows Tomcat environment. I exported the certificate onto my machine, but am uncertain of how to proceed from there.

EDIT: I tried using OpenSSL to modify the certificate and add it to my keystore as described in the "Refusing to trust certificate in trust store" link and it didn't work. It seems like this is a process that is done by the owner of the certificate, right? I wonder if there's some way I can configure my Java 7 environment to let this certificate through.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The default Java certificate checks are pretty strict, and have apparently gotten stricter. One workaround is to initialize an SSLContext with a custom X509TrustManager. A trust manager that does nothing, i.e. is completely insecure, that I once wrote for testing looks like this:

TrustManager[] trustAllCerts = new TrustManager[]{
   new X509TrustManager() {
      public java.security.cert.X509Certificate[] getAcceptedIssuers()
         {
            return null;
         }
      public void checkClientTrusted(
         java.security.cert.X509Certificate[] certs,
         String authType )
         {
         }
      public void checkServerTrusted(
         java.security.cert.X509Certificate[] certs,
         String authType )
         {
         }
   }
};

Obviously you would want to actually check the certificate chain in a real program. You could then try to initialize an SSLContext with it and call SSLContext.setDefault() if your API has no other way of configuring SSL. If the API uses the default SSL context then this should work.

Key usage does not appear to be the issue in this case as the certificate chain is not self-signed. Testing the URL appears to show that the leaf certificate is not self-signed and (2) the other two certificates in the chain appear to have certificate signing enabled. An alternative possibility is that Java 6 and Java 7 have separate trust stores and the root certificate is not in the Java 7 store. You may want to double-check that. If you have access to OpenSSL, you can get the certificate chain from the server with:

openssl s_client -host www.example.com -port 443 -showcerts

Apparently updating the trust store was the key (pun intended). The OP reports:

I downloaded OpenSSL for Windows 64 and then used this command to download the certificate chain:

openssl s_client -host www.webserviceurl.com -port 443 -showcerts > c:empcertchain_output.crt

Then I want to import it into my browser's keystore like so (from the JDK's home directory/jre/lib/security):

keytool -import -alias ca -file certchain_output.crt -keystore cacerts -storepass changeit

I believe using X509TrustManager could provide an effective solution as well.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...