Java, https and self signed certificate problems on mac os x

Sometimes you must work with self signed certificate on your mac.
It's no problem if all you need is Safari (or any other browser). Just accept this cert and you are almost happy.

Having an application written in java and setting resource's url available only via https… it's quite another story.
The problem is that java declines such connections and does not provide any confirmation dialog or so. It's just not secure and that's enough do close it.
Moreover, because java uses it's own keystore, it doesn't help if you accept it in Safari.

So, at the end you will get Exception like this:
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

The quite "normal" scenario for developer is that he can access one url with https via his browser (after accepting insecure cert), but cannot use it inside developer tool to point to VCS like svn, cvs, git, mercurial.. .
The last time I come into such problem was my new project with redmine, mercurial and IntelliJ IDEA. I had no problem with redmine in Safari, but it was not possible to connect to mercurial via https from IntellJ IDEA…
So, is there any solution for that?
Of course, there is. And in fact, it's very easy to do it, it's super elegant and non destructive. Even more, it changes nothing to other software that you want (in my scenario it's IntelliJ IDEA).

So, the following are steps you need to do to get rid of that problem.
I assume, that you are a developer, so you know how to do some easy system tasks
  1. Connect the site with self signed certificate with browser (not necessary the exact link, you just need the host certificate).
  2. Accept this self signed certificate and add it to your system keystore.
  3. Find it in your keystore and export it to some file, lets say /tmp/cert.cer
  4. Make copy of java system CA certs into your tmp folder:
    cp /Library/Java/Home/lib/security/cacerts /tmp/local_cacerts
  5. Add this self signed certificate to this keystore copy:
    keytool -import -trustcacerts -keystore /tmp/local_cacerts -noprompt -file /tmp/cert.cer
  6. When prompted for password enter changeit (or any other if you change the standard one).


So, what you have now? You have a copy of java standard CA certs (so you didn't change anything for now) with the self signed certificate added as a trusted one.
If you want, you can grab the cert file in any other way, the method with browser, provided above, is easy and in fact (well, in my case) I have done it anyway.

So, for now nothing happen. The following is the clue to push any java based program on mac os x to work with the new keystore you have prepared (with your problematic certificate, of course).
The solution is very easy, just find your app in
Applications, right-click on it and choose "show package contents" (in mac os x application is a folder - bundle presented with icon and double click action to run it, not open like any other folder).
Find the file
Info.plist inside folder Contents, like on the screenshot below:
info-plist-example


Then open it with any text editor you like. It's an xml file, so vi, Text Wrangler, Text Edit, Dashcode, …, are enough good.
Find the
<key>VMOptions</key>
and the string element after it.
Now, it's the easiest part. Just append two system properties pointing to your new keystore and password:

-Djavax.net.ssl.trustStore=/tmp/local_cacerts -Djavax.net.ssl.trustStorePassword=changeit

Of course, the /tmp path is not the best you can choose. Just copy it to anywhere you want and enter the full path.
So, you should finish with sth like this:
Voila_Capture49

And that's all. Just save, close and start your app. It will work as before except the fact, that your self signed certificate is now trusted.

As I said before: super easy, not harmful neither to you nor your system, changes the security for only the app you want and you can use it with any software you want.

Of course, if that's your application and you have access to it's source code you can just add the following:
System.setProperty("javax.net.ssl.trustStore", "/tmp/local_cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
blog comments powered by Disqus