5 Replies Latest reply: Jun 24, 2008 3:15 AM by EJP RSS

    Path does not chain with any of the trust anchor

    843811
      Hi,

      I got the exception when using

      CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
      PKIXCertPathValidatorResult cpv_result =
      (PKIXCertPathValidatorResult) cpv.validate(cp, params);

      java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
      at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:195)
           at java.security.cert.CertPathValidator.validate(CertPathValidator.java:206)
      ...

      I am using a valid root certificate and valid user certificate from verisign.

      Any idea?


      Thanks.
        • 1. Re: Path does not chain with any of the trust anchor
          843811
          Never mind. I got the answer myself.
          • 2. Re: Path does not chain with any of the trust anchor
            EJP
            Don't tell us, make sure you keep it a secret. And keep asking here for help. This forum is just for you only.
            • 3. Re: Path does not chain with any of the trust anchor
              843811
              I figured it out too...
              • 4. Re: Path does not chain with any of the trust anchor
                843811
                No, seriously.

                Bottom line, I needed to get a client side certificate for a remote server installed into my application during run-time in order to make a successful SSL connection to that remote server.

                I found TONS of really long winded "expert" advice blogs out there (abstractly) detailing how I need to use JSSE and get my cert into the mix.
                They were advising that I might want to use the "keygen" tool to do this, or some other command-line based insanity.
                BTW, the JSSE "documentation" Sucks...
                I am not interested in becoming a SSL Guru or keygen master, but rather "get-er-done" developer.

                I decided to reply to this post since I thought this was the funniest of them all, and the sense of humor here deserved the answer and explanation.

                So I figured it out MacGyver style.

                I had to use Mozilla's firefox and the "certificate viewer" plugin to export the website's certificate to a file.
                Installed certview plus 1.3 into Firefox 2.0.0.14 from https://addons.mozilla.org/en-US/firefox/addon/1964

                Inside Firefox Went into Tools-->Certificate Manager
                Clicked the Web Sites Tab
                Selected the Certificate for www.airlineplanner.com
                Click the view button
                Click the Export button
                Specify the file name "www.MYREMOTESITE.com.cer"
                Save file locally as type: PEM

                Then use JAVA to import the certificate into my program during runtime

                I was able to make SSL connections to the site programmatically using both HTTPSSocket connection and SSLSocket

                Here is the code so you can see it also.

                BTW, this totally sucked to get to this point. I really hope that people read my post here with instructions who have SSL needs here because trying to navigate through the JSSE documentation and other help blogs etc. were worthless and annoying...

                Below is a section that shows the order of the calls required to do some communication on the remote site
                          
                {//Main code
                          KeyStore keystore = loadCertificates();
                
                          SSLContext sslContext = initializeSSLContext(keystore);
                
                          SSLSocketFactory socketFactory = sslContext.getSocketFactory();
                
                          //Can use the following HttpsURLConnection connection to make https calls if needed.
                
                          HttpsURLConnection urlc = establishHTTPSConnection(socketFactory,"www.myremotehost.com");
                
                          //Can use the following SSLSocket connection as you like now.
                          SSLSocket s = (SSLSocket) socketFactory.createSocket("myremotehost.com", 443);  
                
                }
                my loadCertificates method
                  private static KeyStore loadCertificates() throws IOException,
                      FileNotFoundException, CertificateException, KeyStoreException,
                      NoSuchAlgorithmException, InvalidAlgorithmParameterException {
                    KeyStore keystore = null;
                    //Must use the stupid cacerts file as a base cert store to add my downloaded cert to.
                    String jDKCacertsfilename = "cacerts".replace('/', File.separatorChar);
                    //  Nothing special here, just requires some non-null/blank bogus password unless there really is one
                    String cacertsPassword = "changeit";
                    System.setProperty("javax.net.ssl.trustStore", jDKCacertsfilename);
                
                    // Load the JDK's cacerts keystore file
                    FileInputStream is = new FileInputStream(jDKCacertsfilename);
                    keystore = KeyStore.getInstance(KeyStore.getDefaultType());
                    keystore.load(is, cacertsPassword.toCharArray());
                    
                    //    Any of the following local custom certificates WORKS !!!!!!!!!!!!!
                    String myCertfileName = "www.MYREMOTESITE.com.cer".replace('/', File.separatorChar);
                    File myFile = new File(myCertfileName);
                    FileInputStream myis = new FileInputStream(myFile);
                
                    CertificateFactory cf = CertificateFactory.getInstance("X.509");
                    Certificate mycert = cf.generateCertificate(myis);
                
                
                    keystore.setCertificateEntry("PROD5_VeriSign", mycert);
                    return keystore;
                  }
                Now the the certificate is loaded initialize the context
                  private static SSLContext initializeSSLContext(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
                    SSLContext sslContext = SSLContext.getInstance(SSL_VERSION);
                    String defaultAlg = TrustManagerFactory.getDefaultAlgorithm();
                    TrustManagerFactory tmf =  TrustManagerFactory.getInstance(defaultAlg);
                    tmf.init(keystore);
                    TrustManager tms[] = tmf.getTrustManagers();
                    sslContext.init(null, tms, null);
                    return sslContext;
                  }
                Now obtain a connection to the site via HTTPS if you wish.
                  private static HttpsURLConnection establishHTTPSConnection(SSLSocketFactory socketFactory, String theUrl) throws IOException, MalformedURLException, ProtocolException {
                    HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
                
                    HttpsURLConnection urlc = (HttpsURLConnection) (new URL(theUrl)).openConnection();
                    urlc.setAllowUserInteraction(true);
                    urlc.setRequestMethod("POST");
                    urlc.setSSLSocketFactory(socketFactory);
                    urlc.connect();
                    return urlc;
                  }
                Hope this helps...

                There is a lot of stuff I am not describing here, but feel free to cut and paste the code and go through it yourself in your own project.

                Sincerely,

                Rodney G. Wiltshire Jr.

                Edited by: RodamisP on Jun 23, 2008 2:47 PM
                • 5. Re: Path does not chain with any of the trust anchor
                  EJP
                  Bottom line, I needed to get a client side certificate for a remote server installed into my application during run-time in order to make a successful SSL connection to that remote server.
                  Bottom line is that you have just broken SSL.
                  They were advising that I might want to use the "keygen" tool to do this, or some other command-line based insanity.
                  It's not insanity at all. Which servers you trust is an installation issue, not an issue of what code you write. You're distributing the cert file, what's wrong with going one extra step and importing it into a truststore and distributing that? At least that way you get password protection. Your way is just plain insecure. Anybody can substitute any certificate they like.
                  I am not interested in becoming a SSL Guru
                  Then you shouldn't be carrying out security work if you're not prepared to understand the issues. You'll just build an insecure system. As you have. This is worse than doing nothing.
                  //Must use the stupid cacerts file as a base cert store to add my downloaded cert to.
                  The cacerts file, i.e. a list of trusted certificate issures, is the foundation of JSSE and PKI security. There is nothing 'stupid' about it whatsoever. The stupidity in this thread lies elsewhere.
                  System.setProperty("javax.net.ssl.trustStore", jDKCacertsfilename);
                  This line has zero effect, as you are defining your own truststore programmatically.
                  Hope this helps...
                  Not in the least. It's entirely insecure. keytool -import would have been a better option.