Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > truststore in jar?

Reply
Thread Tools

truststore in jar?

 
 
Tim Ward
Guest
Posts: n/a
 
      05-24-2006
Scenario: Java application distributed as a single jar file. It now needs to
make SSL connections where it used to make TCP connections. So it needs a
truststore so as to be able to validate the certificate presented by the
server.

I've got all that working fine with the truststore in a separate disk file,
but that's no use for distributing the application. So, if I include the
truststore in the jar file (along with the images and other resource files)
how do I make the Java SSL system use it?

(The only suggestion I've found is to include it as a resource, then write
some code to copy this to a disk file before setting the system property.
This is nonsense, mostly because it is obviously utterly silly but also
because it's less than obvious that you can guarantee to find somewhere to
put the file safely and reliably.)

--
Tim Ward
Brett Ward Limited - www.brettward.co.uk


 
Reply With Quote
 
 
 
 
EJP
Guest
Posts: n/a
 
      05-24-2006
Tim Ward wrote:
>
> So, if I include the
> truststore in the jar file (along with the images and other resource files)
> how do I make the Java SSL system use it?


You can do it by getting a javax.net.ssl.SSLContext via
SSLContext.getInstance, then call SSLContext.init(). The second
parameter is an array of TrustManagers. You can define your own
TrustManager to load your truststore from wherever you like, using in
your case java.security.KeyStore.load() from your truststore resource's
input stream, and implement the X509TrustManager API to respond
appropriately when SSL asks you any of those questions by looking in
that KeyStore. You then use that SSLContext to obtain your SSL socket
factories, use them to get your SSLSockets, and away you go.

However having said all that I would probably recommend that you rethink
the strategy instead. What happens when your server certificate expires?
Another software distribution? What about those clients you aren't able
to reach with your distribution any more, for whatever reason? do you
really want to cut them off at the knees?

All your clients really need in their truststores is a root certificate
to which your server certificate leads, and actually Java's truststore
should already have one of those. It ships with lots of root certs for
Verisign, CyberTrust, Equifax, Baltimore,Entrust, GeoTrust, Thawte, &c,
and your certificate is almost certainly signed by someone whose cert
chain leads back to one of those.
 
Reply With Quote
 
 
 
 
Tim Ward
Guest
Posts: n/a
 
      05-24-2006
"EJP" <(E-Mail Removed)> wrote in message
news:FgZcg.10061$(E-Mail Removed)...
> Tim Ward wrote:
> >
> > So, if I include the
> > truststore in the jar file (along with the images and other resource

files)
> > how do I make the Java SSL system use it?

>
> You can do it by getting a javax.net.ssl.SSLContext via
> SSLContext.getInstance, then call SSLContext.init(). The second
> parameter is an array of TrustManagers. You can define your own
> TrustManager ...


I was beginning to think that was probably the way forward ... thanks for
confirming it. (Before I'd written lots of code trying out various wrong
approaches.)

> However having said all that I would probably recommend that you rethink
> the strategy instead. What happens when your server certificate expires?
> Another software distribution?


Well, not when any individual server certificate expires, only when the
private root certificate is compromised ... in which case another
distribution of my little application will be the least of my client's
worries.

> What about those clients you aren't able
> to reach with your distribution any more, for whatever reason? do you
> really want to cut them off at the knees?


Not my decision, I just implement the spec. But the answer could well be
something like: "yes, cutting them off is fine, because if they can't be
reached for a software distribution they probably also can't be reached to
be billed for their support contract".

> All your clients really need in their truststores is a root certificate
> to which your server certificate leads, and actually Java's truststore
> ...ships with lots of root certs ...
> and your certificate is almost certainly signed by someone whose cert
> chain leads back to one of those.


Nope, it's a private certificate hierarchy.

Thanks again.

--
Tim Ward
Brett Ward Limited - www.brettward.co.uk


 
Reply With Quote
 
Tim Ward
Guest
Posts: n/a
 
      05-24-2006
"EJP" <(E-Mail Removed)> wrote in message
news:FgZcg.10061$(E-Mail Removed)...
> Tim Ward wrote:
> >
> > So, if I include the
> > truststore in the jar file (along with the images and other resource

files)
> > how do I make the Java SSL system use it?

>
> You can do it by getting a javax.net.ssl.SSLContext via
> SSLContext.getInstance, then call SSLContext.init(). The second
> parameter is an array of TrustManagers. You can define your own
> TrustManager to load your truststore from wherever you like, using in
> your case java.security.KeyStore.load() from your truststore resource's
> input stream, and implement the X509TrustManager API to respond
> appropriately when SSL asks you any of those questions by looking in
> that KeyStore. You then use that SSLContext to obtain your SSL socket
> factories, use them to get your SSLSockets, and away you go.


.... except that I don't want to try to understand how to write code to
"implement the X509TrustManager API" because all that code already exists: I
don't want any different algorithms to what's built in, only different data.

Instead, why can't I:

(1) get a TrustManagerFactory
(2) make a KeyStore and load it from the resource as you say
(3) use this KeyStore to init() the TrustManagerFactory
(4) get the TrustManagerFactory to make me a TrustManager
(5) pass this to SSLContext.init() and continue as you say

ie, instead of writing code to implement X509TrustManager, get one from a
customised TrustManagerFactory?

In which case, all I need to know is which version of
TrustManagerFactory.instance() to call and what parameters to pass it in
order to obtain a TrustManagerFactory that will behave in exactly the same
way as the default one except that it's got a different set of trusted root
certificates? Ah, probably I just pass it getDefaultAlgorithm()?

--
Tim Ward
Brett Ward Limited - www.brettward.co.uk


 
Reply With Quote
 
Rogan Dawes
Guest
Posts: n/a
 
      05-24-2006
Tim Ward wrote:
> "EJP" <(E-Mail Removed)> wrote in message
> news:FgZcg.10061$(E-Mail Removed)...
>> Tim Ward wrote:
>>> So, if I include the
>>> truststore in the jar file (along with the images and other resource

> files)
>>> how do I make the Java SSL system use it?

>> You can do it by getting a javax.net.ssl.SSLContext via
>> SSLContext.getInstance, then call SSLContext.init(). The second
>> parameter is an array of TrustManagers. You can define your own
>> TrustManager to load your truststore from wherever you like, using in
>> your case java.security.KeyStore.load() from your truststore resource's
>> input stream, and implement the X509TrustManager API to respond
>> appropriately when SSL asks you any of those questions by looking in
>> that KeyStore. You then use that SSLContext to obtain your SSL socket
>> factories, use them to get your SSLSockets, and away you go.

>
> ... except that I don't want to try to understand how to write code to
> "implement the X509TrustManager API" because all that code already exists: I
> don't want any different algorithms to what's built in, only different data.
>
> Instead, why can't I:
>
> (1) get a TrustManagerFactory
> (2) make a KeyStore and load it from the resource as you say
> (3) use this KeyStore to init() the TrustManagerFactory
> (4) get the TrustManagerFactory to make me a TrustManager
> (5) pass this to SSLContext.init() and continue as you say
>
> ie, instead of writing code to implement X509TrustManager, get one from a
> customised TrustManagerFactory?
>
> In which case, all I need to know is which version of
> TrustManagerFactory.instance() to call and what parameters to pass it in
> order to obtain a TrustManagerFactory that will behave in exactly the same
> way as the default one except that it's got a different set of trusted root
> certificates? Ah, probably I just pass it getDefaultAlgorithm()?
>
> --
> Tim Ward
> Brett Ward Limited - www.brettward.co.uk
>
>


You may find the following article interesting:

<http://www.devx.com/tips/Tip/30077>

Obviously you don't need the GUI. But it shows a pretty minimal
implementation of an X509TrustManager

Regards,

Rogan
 
Reply With Quote
 
EJP
Guest
Posts: n/a
 
      05-25-2006
Tim Ward wrote:
>
> Instead, why can't I:
>
> ...
>
> ie, instead of writing code to implement X509TrustManager, get one from a
> customised TrustManagerFactory?
>
> ...


This all sounds OK, stupid of me not to think of it.
 
Reply With Quote
 
Tim Ward
Guest
Posts: n/a
 
      05-26-2006
"EJP" <(E-Mail Removed)> wrote in message
news:J98dg.10227$(E-Mail Removed)...
> Tim Ward wrote:
> >
> > Instead, why can't I:
> > ...
> >
> > ie, instead of writing code to implement X509TrustManager, get one from

a
> > customised TrustManagerFactory?
> > ...

>
> This all sounds OK, stupid of me not to think of it.


For any future readers of this thread: that does in fact work.

--
Tim Ward
Brett Ward Limited - www.brettward.co.uk


 
Reply With Quote
 
chrispix chrispix is offline
Junior Member
Join Date: Jul 2006
Posts: 1
 
      07-22-2006
I'm trying to do this very thing, but I still get the dreaded javax.net.ssl.SSLHandshakeException. Here's a snippet of my code. Am I interpreting you correctly?

Code:
// just to be sure
System.clearProperty("javax.net.ssl.keyStore");

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream keystoreStream = TestCreateSchedule.class.getResourceAsStream("/myTrust.jks");
keystore.load(keystoreStream, null);
trustManagerFactory.init(keystore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustManagers, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

// using commons-httpclient to test
HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod("https://serverurl:8002/path/to/service");
httpclient.executeMethod(httpget);
I've verified that it is correctly reading myTrust.jks from the jar file, and that I can make a connection to https://serverurl:8002/path/to/service if I set the javax.net.ssl.keyStore system property to point to the keystore in the filesystem. Am I missing something?

Here's the stack trace:

Code:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.Su
nCertPathBuilderException: unable to find valid certification path to requested target
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(Unknown Source)
        at com.sun.net.ssl.internal.ssl.AppOutputStream.write(Unknown Source)
        at org.apache.commons.httpclient.HttpConnection$WrappedOutputStream.write(HttpConnection.java:1368)
        at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
        at java.io.BufferedOutputStream.flush(Unknown Source)
        at org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(HttpConnection.java:799)
        at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2277)
        at org.apache.commons.httpclient.HttpMethodBase.processRequest(HttpMethodBase.java:2657)
        at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1093)
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:675)
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:529)
 

Last edited by chrispix; 07-24-2006 at 07:19 PM..
Reply With Quote
 
jacques jacques is offline
Junior Member
Join Date: Mar 2007
Posts: 1
 
      03-19-2007
Hi,

You should try this :
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactor y.getDefaultAlgorithm());
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream keystoreStream = ClassLoader.getSystemResourceAsStream("myTrust.jks ");
keystore.load(keystoreStream, "myPassword".toCharArray());
trustManagerFactory.init(keystore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustManagers, null);
SSLContext.setDefault(sc);

It works on my side with the axis librairy
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how to force rereading of truststore Marc Java 0 06-13-2008 03:44 PM
OpenSSL/SOAP - keystore/truststore Christopher Wilson Ruby 6 03-06-2008 11:29 PM
Set a KeyStore as the system property javax.net.ssl.trustStore value oziris Java 3 09-29-2005 11:05 PM
Using system property 'javax.net.ssl.trustStore' with an applet mike Java 0 02-26-2004 05:45 PM



Advertisments