0

First I would like to say that I am discovering the world of SSL socket and there is not so much material online, I've went through most of the topics on StackOverflow, and I am still confused with the notions of TrustManager, KeyStore, HostNameVerfier... So I have to code a Java client (One-Way SSL) to connect with some servers using SSL. I am making three behaviors, the native one of Android (I belive it's if the cert is not trusted it does not process to the handshake). A Naive one, with a custom TrustManager with empty checkServerTrusted function. And now I want to use the HostNameVerfier to allow all the hostname. But honestly I am a little bit lost and I've searched since days and days and there is no good material about android ssl on the internet. This is my code so far:

Naive custom TrustManager (empty checkServerTrusted)

SSLContext sslContext = SSLContext.getInstance("SSL");
TrustManager trustManagerNaive =    new X509TrustManager(){
        @Override
        public void checkClientTrusted(
                X509Certificate[] chain,
                String authType)
                throws CertificateException {
            // TODO Auto-generated method stub
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void checkServerTrusted(
                X509Certificate[] chain,
                String authType)
                throws CertificateException {
            // TODO Auto-generated method stub
        }
    };

sslContext.init(null, new TrustManager[]{trustManagerNaive}, null);

SSLSocketFactory socketFactory = (SSLSocketFactory)sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket)socketFactory.createSocket(host, Integer.parseInt(port_number_et.getText().toString()));

//Native Android behavior (does not accept any untrusted certificate)
SSLSocketFactory socketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket)socketFactory.createSocket(host, Integer.parseInt(port_number_et.getText().toString()));                      
Darek Kay
  • 15,827
  • 7
  • 64
  • 61
aress31
  • 340
  • 5
  • 20

1 Answers1

0

Here is a running example with an "untrusted" certificate:

KeyStore keyStore = KeyStore.getInstance("BKS");
InputStream in = getContext().getAssets().open(Constants.KEYSTORE_FILENAME);
keyStore.load(in, Constants.KEYSTORE_PASSWORD);
in.close();

SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore);
socketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
registry.register(new Scheme("https", socketFactory, 443));
BasicHttpParams basicHttpParams = new BasicHttpParams();
HttpProtocolParams.setVersion(basicHttpParams, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(basicHttpParams, HTTP.UTF_8);
ThreadSafeClientConnManager ccm = new ThreadSafeClientConnManager(basicHttpParams, registry);

httpClient = new DefaultHttpClient(ccm, basicHttpParams);

Some explanations:

  • Create a keystore with the untrusted certificate
  • Load the keystore and set it in the SSLSocketFactory
  • Set hostnameVerifier to ALLOW_ALL_HOSTNAME_VERIFIER (because the certificate is untrusted)

Then you can use this httpClient for http or https requests as follows:

httpClient.execute(httpGet, new BasicHttpContext());
Lorenz Pfisterer
  • 802
  • 7
  • 17
  • Thank you for this answer but I think that in my case I do not need a keystore as my client does not need to be authentified. Moreover I am not using Http but just normal sockets. Plus as I said in my post the method setHostnameVerifier is not available on my socketfactory object. – aress31 Mar 18 '15 at 13:35
  • If you want to create a ssl connection a certificate is needed for encrypting the data. If you have an unverified certificate on server side, you need to download this certificate and put it in the keyStore of the SSLSocketFactory. Otherwise it makes no sense to use a ssl connection. But if you if you want to do so, here is a solution to allow everything: http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https – Lorenz Pfisterer Mar 18 '15 at 13:43
  • Actually I want it to do not work, I want it to allow everything I am working on a subject to show the flows on the android ssl connection, and I want to make a client (which does not have to authentifiate himself) which connect to server no matter the validness of the certificate. It should accept everything from everyone. – aress31 Mar 18 '15 at 13:48
  • So you can use the solution of the link I posted in the last comment. This will work, but nullifies the entire purpose of ssl – Lorenz Pfisterer Mar 18 '15 at 13:57
  • Yeah I would like to use it but as I told you I think that setHostnameVerifier is an old method because it is not available anymore as for the constructor of SSLSocketFactory it should not take any argument. My IDE (eclipse) is saying that at least. – aress31 Mar 18 '15 at 14:07