Implement SSL in Android


Please follow this links for implement SSL in Android :
http://stackoverflow.com/questions/1217141/self-signed-ssl-acceptance-android#answer-15531475

faced this issue yesterday, while migrating our company’s RESTful API to HTTPS, but using self-signed SSL certs.

I’ve looking everywhere but all the “correct” marked answers I’ve found consisted on disabling certificate validation, clearly overriding all the sense of SSL.

I finally came to a solution.

Create Local KeyStore

To enable your app to validate your self-signed certificates, you need to provide a custom keystore with the certificates in a manner that Android can trust your endpoint.

The format for such custom keystores is “BKS” from BouncyCastle, so you need the 1.46 version of BouncyCastleProvider that you can download Here

You also need your self-signed certificate, i will assume i’ts named self_cert.pem

Now the command for creating your keystore is

$ keytool -import -v -trustcacerts -alias 0 \
-file *PATH_TO_SELF_CERT.PEM* \
-keystore *PATH_TO_KEYSTORE* \
-storetype BKS \
-provider org.bouncycastle.jce.provider.BouncyCastleProvider \
-providerpath *PATH_TO_bcprov-jdk15on-146.jar* \
-storepass *STOREPASS*
PATH_TO_KEYSTORE points to a file where your keystore will be created, it MUST NOT EXIST

PATH_TO_bcprov-jdk15on-146.jar.JAR is the path to the downloaded .jar libary.

STOREPASS is your newly created keystore password.

Include KeyStore on your Application

Copy your newly created keystore from PATH_TO_KEYSTORE to res/raw/certs.bks (certs.bks is just the file name, you can use whatever name you wish)

Create a key in res/values/strings.xml with

1
2
3
4
5
<resources>

    <string name="store_pass">*STOREPASS*</string>

</resources>

Create a this class that inherits DefaultHttpClient

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import android.content.Context;
import android.util.Log;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;

import java.io.IOException;
import java.io.InputStream;
import java.security.*;

public class MyHttpClient extends DefaultHttpClient {

    private static Context appContext = null;
    private static HttpParams params = null;
    private static SchemeRegistry schmReg = null;
    private static Scheme httpsScheme = null;
    private static Scheme httpScheme = null;
    private static String TAG = "MyHttpClient";

    public MyHttpClient(Context myContext) {

        appContext = myContext;

        if (httpScheme == null || httpsScheme == null) {
            httpScheme = new Scheme("http", PlainSocketFactory.getSocketFactory(), 80);
            httpsScheme = new Scheme("https", mySSLSocketFactory(), 443);
        }

        getConnectionManager().getSchemeRegistry().register(httpScheme);
        getConnectionManager().getSchemeRegistry().register(httpsScheme);

    }

    private SSLSocketFactory mySSLSocketFactory() {
        SSLSocketFactory ret = null;
        try {
            final KeyStore ks = KeyStore.getInstance("BKS");

            final InputStream inputStream = appContext.getResources().openRawResource(R.raw.certs);

            ks.load(inputStream, appContext.getString(R.string.store_pass).toCharArray());
            inputStream.close();

            ret = new SSLSocketFactory(ks);
        } catch (UnrecoverableKeyException ex) {
            Log.d(TAG, ex.getMessage());
        } catch (KeyStoreException ex) {
            Log.d(TAG, ex.getMessage());
        } catch (KeyManagementException ex) {
            Log.d(TAG, ex.getMessage());
        } catch (NoSuchAlgorithmException ex) {
            Log.d(TAG, ex.getMessage());
        } catch (IOException ex) {
            Log.d(TAG, ex.getMessage());
        } catch (Exception ex) {
            Log.d(TAG, ex.getMessage());
        } finally {
            return ret;
        }
    }
}

Now simply use an instance of MyHttpClient as you would with DefaultHttpClient to make your https queries, and it will use and validate correctly your self-signed SSL certificates.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
HttpResponse httpResponse;

HttpPost httpQuery = new HttpPost("https://yourserver.com");
… set up your query …

MyHttpClient myClient = new MyHttpClient(myContext);

try{

    httpResponse = myClient.(peticionHttp);

    // Check for 200 OK code
    if (httpResponse.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_OK) {
        … do whatever you want with your response …
    }

}catch (Exception ex){
    Log.d("httpError", ex.getMessage());
}

Cheers!


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.