Tuesday, September 18, 2007

HOWTO: setup Java to trust unsigned SSL CERTs

Overview
If you have an application that needs to talk to a web service (or page) that uses SSL, you may get an ugly error the first time you connect.

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


This is probably because you have a self-signed CERT. This is ok and can be dealt with easily following a few simple steps. Yes the following looks like a lot of steps but I was very verbose.... as usual.

Technique
There are a few steps you need to follow to get your JAVA application to trust the self-signed CERT.

Export the Site's CERT
  1. Visit your target URL (web service or whatever) using IE 6.0. I am not sure how to do this using Firefox.
  2. Doubleclick on the "gold lock" symbol at the bottom of the browser.
  3. You will get a "Certificate" window. Select the "Details" tab and click "Copy to File...". A wizard will open
  4. Click "Next" and you will see "Export File Format". Select "Base-64 encoded X.509 (.CER). Click "Next"
  5. Select a filename and location. Click "Next".
  6. Click Finish. You have now saved the cert. The file should look like a block of letters and numbers in a text editor.
Load the CERT into a keystore
There are probably more then one way to do this. I prefer to use a small application I found called portecle. In a few clicks you can create a keystore and import a CERT into it.

Load the keystore of Trusted CERTs
My preferred way is to include a properties file within my JAR and then use that to point to an external keystore (JKS) file.

The following code can be executed at application startup. Once done, it should work for the life of your application.

Properties defaultProps = new Properties();
InputStream in;
try {
in = ArkaProWSClient.class.getResourceAsStream("/mypackage/cert.properties");
defaultProps.load(in);
in.close();
System.setProperty("javax.net.ssl.trustStore",defaultProps.getProperty("javax.net.ssl.trustStore"));
System.out.println("DEBUG: " + defaultProps.getProperty("javax.net.ssl.trustStore"));

} catch (Exception ioex) {
ioex.printStackTrace();
} // end-try-catch
The cert.properties file simply holds the path to the keystore.
javax.net.ssl.trustStore=C:\\certs\\trustcert.jks
This code will
  1. open the properties file which is located in /mypackage/ within the jar
  2. set javax.net.ssl.trustStore system property to the location of my JKS file. This value comes from the cert.properties file.
Now the error will go away and you should be able to access SSL resources. Although I have not tested it fully, I am pretty sure you can fill you keystore with more then one cert allowing you to access many resources from the same application.

Another way to do this is to use an environment variable
java -Djavax.net.ssl.trustStore="C:\certs\trustcert.jks" -jar dist\SSLClient.jar
Final Thoughts
This procedure should allow your application to access SSL protected data that is self-signed. If anyone know how to get the CERT using Firefox, let me know.

1 comment:

Gary van der Merwe said...

Steps to export certificate file in Firefox (I'm using ver 9. I think this will work from ver 3.6, but I'm not sure):

1. Click on the [favicon + host name] in the location bar.
2. Click the [More Information ...] button in the popup.
3. Click on [View Certificate] button.
4. Click on [Details] tab.
5. Click on [Export...] button.
6. Choose file name and path, and save.