Replace System.setProperty(....) - java

I have this simple JMX client
public void testTomcatBasicAuthentication() throws Exception
{
System.out.println("Test Server Basic Authentication");
try
{
String truststore = "C:\\client.jks";
String trustStorePassword = "password";
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://xxx.xxx.xxx.xxx:9999/jmxrmi");
HashMap environment = new HashMap();
String[] credentials = new String[]
{
"user", "passwd"
};
environment.put(JMXConnector.CREDENTIALS, credentials);
// environment.put("javax.net.ssl.trustStore", truststore);
// environment.put("javax.net.ssl.trustStorePassword", trustStorePassword);
// environment.put("javax.net.ssl.keyStore", truststore);
// environment.put("javax.net.ssl.keyStorePassword", trustStorePassword);
KeyManager[] kms = getKeyManagers(truststore, trustStorePassword);
TrustManager[] tms = getTrustManagers(truststore, trustStorePassword);
System.setProperty("javax.net.ssl.trustStore", truststore);
System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
System.setProperty("javax.net.ssl.keyStore", truststore);
System.setProperty("javax.net.ssl.keyStorePassword", trustStorePassword);
JMXConnector jmxc = JMXConnectorFactory.connect(url, environment);
MBeanServerConnection server = jmxc.getMBeanServerConnection();
Set<ObjectName> s2 = server.queryNames(new ObjectName("Catalina:type=Server,*"), null);
for (ObjectName obj : s2)
{
ObjectName objname = new ObjectName(obj.getCanonicalName());
System.out.println("serverInfo " + server.getAttribute(objname, "serverInfo"));
System.out.println("address " + server.getAttribute(objname, "address"));
System.out.println("stateName " + server.getAttribute(objname, "stateName"));
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
How I can replace System.setProperty(....) with Java code? I don't want to use System.setProperty.
Edit. I found this example
Can we use this code?
KeyManager[] kms = getKeyManagers(truststore, trustStorePassword);
TrustManager[] tms = getTrustManagers(truststore, trustStorePassword);
SslContext.setCurrentSslContext(new SslContext(kms, tms, null));
private static TrustManager[] getTrustManagers(String location, String password)
throws IOException, GeneralSecurityException
{
// First, get the default TrustManagerFactory.
String alg = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmFact = TrustManagerFactory.getInstance(alg);
FileInputStream fis = new FileInputStream(location);
KeyStore ks = KeyStore.getInstance("jks");
ks.load(fis, password.toCharArray());
fis.close();
tmFact.init(ks);
// And now get the TrustManagers
TrustManager[] tms = tmFact.getTrustManagers();
return tms;
}
private static KeyManager[] getKeyManagers(String location, String password)
throws IOException, GeneralSecurityException
{
// First, get the default KeyManagerFactory.
String alg = KeyManagerFactory.getDefaultAlgorithm();
KeyManagerFactory kmFact = KeyManagerFactory.getInstance(alg);
FileInputStream fis = new FileInputStream(location);
KeyStore ks = KeyStore.getInstance("jks");
ks.load(fis, password.toCharArray());
fis.close();
// Now we initialise the KeyManagerFactory with this KeyStore
kmFact.init(ks, password.toCharArray());
// And now get the KeyManagers
KeyManager[] kms = kmFact.getKeyManagers();
return kms;
}
private static KeyStore keyStoreFromCertificateString(String alias, String certificateString)
throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException
{
KeyStore ks = KeyStore.getInstance("jks");
ks.load(null); // Create empty key store
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(new ByteArrayInputStream(certificateString.getBytes()));
ks.setEntry(alias, new KeyStore.TrustedCertificateEntry(cert), null);
return ks;
}
Can you give some idea how we can integrate this code or there should be some other solution?

It seems like it should be relatively easy, but it's not.
You need to pass actual socket factory classes in the environment, see this example. However, the implementations used in that example use the jvm default socket factories. Instead, you need to setup your own SSL*SocketFactory instances with the appropriate key store and trust store. Then you need to implement your own RMI*SocketFactory instances using your configured socket factory(s). You can use the jdk impls as guides, SslRMIClientSocketFactory and SslRMIServerSocketFactory.

I fear your question is not very well formulated. I write you want to replace System.setProperty but for me it looks like, actually you want to use custom trust/key stores.
This has been answered already: Using a custom truststore in java as well as the default one
The example that you have found is only half of the solution. You have to use the respective managers when creating the connections. Something like this:
sslContext.init(null, trustManagers, null);
connection.setSSLSocketFactory(sslContext.getSocketFactory());
Source: https://planet.jboss.org/post/creating_https_connection_without_javax_net_ssl_truststore_property
But if you don't control the actual connection creation you probably have to use the global properties. (Or whatever config mechanism your application server has)

A simple and easy workaround to make this work is to use a separate copy of system properties for each thread as explained very well in here (interestingly, the main question self concerns the same problem as yours). After that, setting keyStore and trustStore on system properties will be thread-local.
Make sure you use different threads for your two different ssl connections.

Related

Secure connection failed to a java server

I tried to secure the connection to my java server, after downloading a certificate(certificate.crt) and adding it to the keystore (keystore.jks) my server run normally and read the certificate.But if I want to consume a service via https://123.456.88.99:1010/myService from the navigator(firefox) I get a PR_END_OF_FILE_ERROR The page you are trying to view cannot be shown because the authenticity of the received data could not be verified.ps : http://123.456.88.99:1010/myService works and consume the service and retrieve data also by using firefox, I think its a problem of private key that the navigator don't get, I really need help, thank you
ps if I try to use a certificate that I create using keytool it works
private void startHttpsServer(RestFactory factory, int port, int minWorkers, int maxWorkers, int socketTimeoutMS,
boolean keepConnection, boolean ignoreContentLength, boolean debug, Compression compression, boolean useClassicServer, boolean requireCertificate) throws Exception {
String alias = "server-alias";
String pwd = "changeit";
char [] storepass = pwd.toCharArray();
String keystoreName = "c:\\keystore.jks";
FileInputStream in = new FileInputStream(keystoreName);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(in, storepass);
Certificate cert = keystore.getCertificate(alias);
Log.debug("the certification is here : " + cert);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
char [] keypass = pwd.toCharArray();
kmf.init(keystore, keypass);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLEngine engine = sslContext.createSSLEngine();
engine.setEnabledCipherSuites(new String[] {"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
SSLParameters defaultSSLParameters = sslContext.getDefaultSSLParameters();
engine.setSSLParameters(defaultSSLParameters);
HttpsRestServer server = new HttpsRestServer(factory, port, minWorkers, maxWorkers, debug, compression, keystore, keypass, false);
server.addCleaner(new CleanupListener() {
#Override
public void cleanup(CleanupEvent event) {
Database.disconnectAllThreadConnections(event.thread, false);
}
});
this.servers.add(server);
log.info("Starting classic HTTPS replication server on port " + port);
server.start();
log.info("Secure XML replication server started on port " + port);
}

How to load a certificate from "Credential storage"?

My network code is written in NDK (cURL + OpenSSL) and I'd like to use a certificate from Android's credential storage as a client certificate for a SSL connection. Moreover, I'd like to offer a list of available certificates to the user, so he can choose the certificate for the connection. Unfortunately, I cannot obtain a certificate from the key storage.
I installed a client certificate to "Credential storage" (Settings -> Secutrity -> ...) on my Android device (5.0.2), but I'm not able to access it from Java. I tried to call following code, but the key storage is empy, athough the certificate is installed in the Credential storage:
//KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
Enumeration<String> aliases = ks.aliases();
while(aliases.hasMoreElements()) {
String alias = (String)aliases.nextElement();
Log.i("app", "alias name: " + alias);
Certificate certificate = ks.getCertificate(alias);
Log.i("app", certificate.toString());
}
What am I doing wrong?
User credentials installed on the device are available through Android KeyChain, not Android KeyStore
The KeyChain class provides access to private keys and their corresponding certificate chains in credential storage.
Use choosePrivateKeyAlias ​​to prompt the user for selecting the certificate. The system launches an Activity for the user to select the alias and returns it via a callback. Then use getPrivateKey and getCertificate to recover the key and the corresponding certificate chain
KeyChain.choosePrivateKeyAlias(activity, new KeyChainAliasCallback() {
public void alias(String alias) {
//do something with the selected alias
}
},
new String[] { KeyProperties.KEY_ALGORITHM_RSA, "DSA"}, // List of acceptable key types. null for any
null, // issuer, null for any
null, // host name of server requesting the cert, null if unavailable
-1, // port of server requesting the cert, -1 if unavailable
""); // alias to preselect, null if unavailable
PrivateKey privateKey = KeyChain.getPrivateKey(activity, alias);
X509Certificate chain[] = KeyChain.getCertificateChain(activity, alias);
Try something like this:
X509TrustManager manager = null;
FileInputStream fs = null;
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
try
{
fs = new FileInputStream(System.getProperty("javax.net.ssl.trustStore"));
keyStore.load(fs, null);
}
finally
{
if (fs != null) { fs.close(); }
}
trustManagerFactory.init(keyStore);
TrustManager[] managers = trustManagerFactory.getTrustManagers();
for (TrustManager tm : managers)
{
if (tm instanceof X509TrustManager)
{
manager = (X509TrustManager) tm;
break;
}
}

Creating a HTTPS Server in Java - Where is the local Certificates?

i found some tutorial to handle with https server and a https client. i created some keystore and it works fine. But i have some question which is not clear from the tutorial.
this is my https-server
public class HTTPSServer {
private int port = 9999;
private boolean isServerDone = false;
public static void main(String[] args) {
HTTPSServer server = new HTTPSServer();
server.run();
}
HTTPSServer() {
}
HTTPSServer(int port) {
this.port = port;
}
// Create the and initialize the SSLContext
private SSLContext createSSLContext() {
try {
//Returns keystore object in definied type, here jks
KeyStore keyStore = KeyStore.getInstance("JKS");
//loads the keystore from givin input stream, and the password to unclock jks
keyStore.load(new FileInputStream("x509-ca.jks"), "password".toCharArray());
// Create key manager
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, "password".toCharArray());
KeyManager[] km = keyManagerFactory.getKeyManagers();
// Create trust manager
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
trustManagerFactory.init(keyStore);
TrustManager[] tm = trustManagerFactory.getTrustManagers();
// opens a secure socket with definied protocol
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
//System.out.println(keyStore.getCertificate("root").getPublicKey());
//System.out.println(keyStore.isKeyEntry("root"));
sslContext.init(km, tm, null);
return sslContext;
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
// Start to run the server
public void run() {
SSLContext sslContext = this.createSSLContext();
try {
// Create server socket factory
SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
// Create server socket
SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(this.port);
System.out.println("SSL server started");
while (!isServerDone) {
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
// Start the server thread
new ServerThread(sslSocket).start();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
// Thread handling the socket from client
static class ServerThread extends Thread {
private SSLSocket sslSocket = null;
ServerThread(SSLSocket sslSocket) {
this.sslSocket = sslSocket;
}
public void run() {
sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
//System.out.println("HIER: " + sslSocket.getHandshakeSession());
//Klappt nicht, auch nicht, wenn der Client diese Zeile ebenfalls besitzt
//sslSocket.setEnabledCipherSuites(new String[]{"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"});
try {
// Start handshake
sslSocket.startHandshake();
// Get session after the connection is established
SSLSession sslSession = sslSocket.getSession();
System.out.println(sslSession.getPeerHost());
System.out.println(sslSession.getLocalCertificates());
System.out.println("\tProtocol : " + sslSession.getProtocol());
System.out.println("\tCipher suite : " + sslSession.getCipherSuite());
System.out.println("\tSession context : " + sslSession.getSessionContext());
//System.out.println("\tPeer pricipal of peer : " + sslSession.getPeerPrincipal());
// Start handling application content
InputStream inputStream = sslSocket.getInputStream();
OutputStream outputStream = sslSocket.getOutputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(outputStream));
String line = null;
String[] suites = sslSocket.getSupportedCipherSuites();
for (int i = 0; i < suites.length; i++) {
//System.out.println(suites[i]);
//System.out.println(sslSession.getCipherSuite());
}
while ((line = bufferedReader.readLine()) != null) {
System.out.println("Inut : " + line);
if (line.trim().isEmpty()) {
break;
}
}
// Write data
printWriter.print("HTTP/1.1 200\r\n");
printWriter.flush();
sslSocket.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
And this is my output:
SSL server started
127.0.0.1
null
Protocol : TLSv1.2
Cipher suite : TLS_DH_anon_WITH_AES_128_GCM_SHA256
Session context : sun.security.ssl.SSLSessionContextImpl#781df1a4
I want to know, why the line
System.out.println(sslSession.getLocalCertificates());
prints out "null"?
Thank you a lot, Mira
From the documentation:
Certificate[] getLocalCertificates()
Returns the certificate(s) that were sent to the peer during handshaking.
Note: This method is useful only when using certificate-based cipher suites.
When multiple certificates are available for use in a handshake, the implementation chooses what it considers the "best" certificate chain available, and transmits that to the other side. This method allows the caller to know which certificate chain was actually used.
Returns:
an ordered array of certificates, with the local certificate first followed by any certificate authorities. If no certificates were sent, then null is returned.
The part we care about is "Returns the certificate(s) that were sent to the peer during handshaking.", and "This method is useful only when using certificate-based cipher suites.".
Given that it is returning null, we can assume you are not sending any certificates to the client. But it's also HTTPS, so what gives? Well, it looks like you're using TLS_DH_anon_WITH_AES_128_GCM_SHA256, which is, as the name suggests, anonymous. As per the OpenSSL Wiki:
Anonymous Diffie-Hellman uses Diffie-Hellman, but without authentication. Because the keys used in the exchange are not authenticated, the protocol is susceptible to Man-in-the-Middle attacks. Note: if you use this scheme, a call to SSL_get_peer_certificate will return NULL because you have selected an anonymous protocol. This is the only time SSL_get_peer_certificate is allowed to return NULL under normal circumstances.
While this is applicable to OpenSSL, it would appear to be the same in Java - that is, you're not using a certificate-based cipher. Someone with more knowledge of TLS would need to jump in, but it looks like AES keys are generated, and they're sent to the client, but the client has no assurance those keys came from you, whereas normally you would generate the keys, and then sign / encrypt (not 100% sure) those keys with an RSA key to prove they came from you.
To fix this, I believe you would need to select a different cipher suite, e.g. TLS_RSA_WITH_AES_128_GCM_SHA256. I'm not 100% sure how you would do this, but that would appear to be the solution.
sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
You are enabling all the anonymous and low-grade cipher suites, so you are allowing the server not to send a certificate, so it doesn't send one, so it doesn't give you one in getLocalCertificates().
Remove this line.

HTTPS with client authentication not working on Android

I'm currently writing an Android App (Min SDK 16) that queries a HTTPS server for data. The server (Apache 2.4 on Debian 8) uses a certificate signed by our own CA and requires clients to also have a certificate signed by it. This works perfectly with Firefox after importing both the CA and the client certificate in PKCS format.
I am, however, unable to get this to work in Android. I'm using HttpsURLConnections, as the Apache HTTP Client has been deprecated for Android recently. Trusting our custom CA works, but as soon as I require the client certificate, I get the following Exception:
java.lang.reflect.InvocationTargetException
[...]
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:282) 
at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:192) 
at eu.olynet.olydorfapp.resources.CustomTrustManager.checkServerTrusted(CustomTrustManager.java:96) 
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:614) 
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method) 
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:406) 
at com.android.okhttp.Connection.upgradeToTls(Connection.java:146) 
at com.android.okhttp.Connection.connect(Connection.java:107) 
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294) 
at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255) 
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206) 
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345) 
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296) 
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503) 
at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:136) 
at org.jboss.resteasy.client.jaxrs.engines.URLConnectionEngine.invoke(URLConnectionEngine.java:49) 
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:436) 
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:102) 
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:64) 
at $Proxy9.getMetaNews(Native Method) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:515) 
at eu.olynet.olydorfapp.resources.ResourceManager.fetchMetaItems(ResourceManager.java:372) 
at eu.olynet.olydorfapp.resources.ResourceManager.getTreeOfMetaItems(ResourceManager.java:542) 
at eu.olynet.olydorfapp.tabs.NewsTab$1.doInBackground(NewsTab.java:51) 
at eu.olynet.olydorfapp.tabs.NewsTab$1.doInBackground(NewsTab.java:45) 
at android.os.AsyncTask$2.call(AsyncTask.java:288) 
at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
at java.lang.Thread.run(Thread.java:841) 
To me this looks like the server certificate cannot be verified, which should not be the case.
This is what the code looks like:
private static final String CA_FILE = "ca.pem";
private static final String CERTIFICATE_FILE = "app_01.pfx";
private static final char[] CERTIFICATE_KEY = "password".toCharArray();
[...]
CertificateFactory cf = CertificateFactory.getInstance("X.509");
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
InputStream ca = this.context.getAssets().open(CA_FILE);
KeyStore trustStore = KeyStore.getInstance("PKCS12");
trustStore.load(null);
Certificate caCert = cf.generateCertificate(ca);
trustStore.setCertificateEntry("CA Name", caCert);
CustomTrustManager tm = new CustomTrustManager(trustStore);
ca.close();
InputStream clientCert = this.context.getAssets().open(CERTIFICATE_FILE);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(clientCert, CERTIFICATE_KEY);
Log.e("KeyStore", "Size: " + keyStore.size());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
kmf.init(keyStore, CERTIFICATE_KEY);
clientCert.close();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{tm}, null);
[...]
((HttpsURLConnection) con).setSSLSocketFactory(sslContext.getSocketFactory());
Relevant function of the CustomTrustManager (where localTrustManager contains just our CA and defaultTrustManager the system's CAs):
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
try {
localTrustManager.checkServerTrusted(chain, authType);
} catch (CertificateException ce) {
defaultTrustManager.checkServerTrusted(chain, authType);
}
}
I've already tried converting the PKCS file to a BKS file (and adapting the KeyStore, of course) without success. I've also seen the similar questions here but none of the solutions worked for me.
I've found that adding the intermediate CA (the one that signed the server's certificate directly) in addition to the root CA worked. I do not understand why this is necessary as verification works fine with just the root CA if no client certificate is required by the server. To me this seems like some kind of bug in the Android implementation of HttpsURLConnections or a related class. Please educate me if I'm wrong.
Working code:
private static final String CA_FILE = "ca.pem";
private static final String INTERMEDIATE_FILE = "intermediate.pem";
private static final String CERTIFICATE_FILE = "app_01.pfx";
private static final char[] CERTIFICATE_KEY = "password".toCharArray();
[...]
CertificateFactory cf = CertificateFactory.getInstance("X.509");
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
/* trust setup */
InputStream ca = this.context.getAssets().open(CA_FILE);
InputStream intermediate = this.context.getAssets().open(INTERMEDIATE_FILE);
KeyStore trustStore = KeyStore.getInstance("PKCS12");
trustStore.load(null);
Certificate caCert = cf.generateCertificate(ca);
Certificate intermediateCert = cf.generateCertificate(intermediate);
trustStore.setCertificateEntry("CA Name", caCert);
trustStore.setCertificateEntry("Intermediate Name", intermediateCert);
CustomTrustManager tm = new CustomTrustManager(trustStore);
ca.close();
intermediate.close();
/* client certificate setup */
InputStream clientCert = this.context.getAssets().open(CERTIFICATE_FILE);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(clientCert, CERTIFICATE_KEY);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
kmf.init(keyStore, CERTIFICATE_KEY);
clientCert.close();
/* SSLContext setup */
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{tm}, null);
[...]
((HttpsURLConnection) con).setSSLSocketFactory(sslContext.getSocketFactory());

facing class cast error with setSSLSocketFactory between two packages

I have created my own SSLSocketFactory as explained in this question
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// Get theraw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
Context context = this.activity;
Resources _resources = context.getResources();
InputStream in = _resources.openRawResource(R.raw.mystore);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "mypassword".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
Actually i need to set this SSLSocketFactory on the HttpsURLConnection before connecting. But when i try to set it on HttpsURLConnection by calling
(HttpsURLConnection )connection.setSSLSocketFactory(trusted);
At this point am facing cast class error between 2 packages org.apache.http.conn.ssl.SSLSocketFactory and javax.net.ssl.SSLSocketFactory.
How to solve this?
Am not getting any exception with the above piece of code.
But the problem is that, when am trying to set the SSLSocketFactory on the HttpsURLConnection using:
(HttpsURLConnection )connection.setSSLSocketFactory(trusted)
It is showing "The method setSSLSocketFactory(SSLSocketFactory) in the type HttpsURLConnection is not applicable for the arguments(SSLSocketFactory)".
Because the method setSSLSocketFactory is there in both the packages.

Categories