users@jersey.java.net

[Jersey] Re: Client - Server SSL communication, 400 Bad Request

From: Jean-Louis FERRER <ferrer.jeanlouis_at_gmail.com>
Date: Tue, 13 Mar 2012 15:26:52 +0100

Hello,

Yes I did set the SSLContext. Here follows the class I am using:

public class ClientHelper {

private static final String keystore_path = "C:/Program
Files/Java/jdk1.6.0/jre/lib/security/myKeystore.jks";
 private static final String keystore_password = "password";

public static ClientConfig configureClient()
 throws NoSuchAlgorithmException, KeyStoreException,
UnrecoverableKeyException {

KeyManager mykm[] = null;

try {
mykm = new KeyManager[] { new MyX509KeyManager(keystore_path,
 keystore_password.toCharArray()) };
} catch (Exception ex) {
ex.printStackTrace();
 }

SSLContext context = null;

try {
 context = SSLContext.getInstance("SSL");
context.init(mykm, null, null);
 } catch (NoSuchAlgorithmException nae) {
nae.printStackTrace();
} catch (KeyManagementException kme) {
 kme.printStackTrace();
}

HTTPSProperties prop = new HTTPSProperties(new HostnameVerifier() {
 public boolean verify(String hostname, SSLSession session) {
System.out.println("verifying: " + hostname);
 return true;
}
}, context);

ClientConfig config = new DefaultClientConfig();
try {
config.getProperties().put(
 HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, prop);
} catch (Exception e) {
 }
return config;
}

// class continues ...

}

That returns the ClientConfig for the Client creation.

The SSLContext has been set to SSL, TLS, PKIX, hasn't changed the outcome.

The keystore has been created using keytool with the certificate that
allows my browser to access the server (well technically not that
certificate, but one exported using the Windows certificates tool)

The MyX509KeyManager is as follows (very close to
http://wiki.open-esb.java.net/attach/RestBCEchoSSL/SslClient.java):

        /**
 * Inspired from
 * http://java.sun.com/javase/6/docs/technotes/guides/security/
 * jsse/JSSERefGuide.html
 *
 */
 static class MyX509KeyManager implements X509KeyManager {

/*
 * The default PKIX X509KeyManager. We'll delegate decisions to it, and
 * fall back to the logic in this class if the default X509KeyManager
 * doesn't trust it.
 */
X509KeyManager pkixKeyManager;

MyX509KeyManager(String keyStore, char[] password) throws Exception {
this(new File(keyStore), password);
 }

MyX509KeyManager(File keyStore, char[] password) throws Exception {
 // create a "default" JSSE X509KeyManager.

KeyStore ks = KeyStore.getInstance("JKS");
 ks.load(new FileInputStream(keyStore), password);

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509",
 "SunJSSE");
kmf.init(ks, password);

KeyManager kms[] = kmf.getKeyManagers();

/*
 * Iterate over the returned keymanagers, look for an instance of
 * X509KeyManager. If found, use that as our "default" key manager.
 */
 for (int i = 0; i < kms.length; i++) {
if (kms[i] instanceof X509KeyManager) {
 pkixKeyManager = (X509KeyManager) kms[i];
return;
}
 }

/*
 * Find some other way to initialize, or else we have to fail the
 * constructor.
 */
throw new Exception("Couldn't initialize");
 }

public PrivateKey getPrivateKey(String arg0) {
return pkixKeyManager.getPrivateKey(arg0);
 }

public java.security.cert.X509Certificate[] getCertificateChain(
 String arg0) {
return pkixKeyManager.getCertificateChain(arg0);
}

public String[] getClientAliases(String arg0, Principal[] arg1) {
return pkixKeyManager.getClientAliases(arg0, arg1);
 }

public String chooseClientAlias(String[] arg0, Principal[] arg1,
 Socket arg2) {
return pkixKeyManager.chooseClientAlias(arg0, arg1, arg2);
 }

public String[] getServerAliases(String arg0, Principal[] arg1) {
 return pkixKeyManager.getServerAliases(arg0, arg1);
}

public String chooseServerAlias(String arg0, Principal[] arg1,
 Socket arg2) {
return pkixKeyManager.chooseServerAlias(arg0, arg1, arg2);
 }
}

Thanks for your time!

Cheers,
JL