Connecting to SSL server from Android with self signed certificate

So I have a SSL Server running and I can connect from a PC. I now want to be able to connect from Android.

Creating the trust store

Android only accepts BKS certificates whereas I have created a CER certificate with keytool.

  • Download portecle
  • Run the program
  • File > New KeyStore > BKS
  • Tools > Import Trusted Certificate > alias = server
  • Save Keystore (pass = keypass) as C:\temp\server.bks
  • Copy the file to the Android project in res/raw/server.bks

Creating the SSLContext

Code for the creation of the SSLClient:

    protected Socket getConnection(String ip, int port) throws IOException  {
        try {
            KeyStore trustStore = KeyStore.getInstance("BKS");
            InputStream trustStoreStream = context.getResources().openRawResource(R.raw.server);
            trustStore.load(trustStoreStream, "keypass".toCharArray());

            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(trustStore);

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            SSLSocketFactory factory = sslContext.getSocketFactory();
            SSLSocket socket = (SSLSocket) factory.createSocket(ip, port);
            socket.setEnabledCipherSuites(SSLUtils.getCipherSuitesWhiteList(socket.getEnabledCipherSuites()));
            return socket;
        } catch (GeneralSecurityException e) {
            Log.e(this.getClass().toString(), "Exception while creating context: ", e);
            throw new IOException("Could not connect to SSL Server", e);
        }
    }

Et voila, that should work fine now.

Note: the SSLUtils class is a custom class that I use to filter out less secure cipher suites. The line that uses it in the code above is not required per se but just in case, this is what the code looks like:

public final class SSLUtils {

    private SSLUtils() { //non instantiable
    }

    public static String[] getCipherSuitesWhiteList(String[] cipherSuites) {
        List<String> whiteList = new ArrayList<>();
        List<String> rejected = new ArrayList<>();
        for (String suite : cipherSuites) {
            String s = suite.toLowerCase();
            if (s.contains("anon") || //reject no anonymous
                    s.contains("export") || //reject no export
                    s.contains("null") || //reject no encryption
                    s.contains("md5") || //reject MD5 (weaknesses)
                    s.contains("_des") || //reject DES (key size too small)
                    s.contains("krb5") || //reject Kerberos: unlikely to be used
                    s.contains("ssl") || //reject ssl (only tls)
                    s.contains("empty")) {    //not sure what this one is
                rejected.add(suite);
            } else {
                whiteList.add(suite);
            }
        }
        Log.d(this.getClass().toString(), "Rejected Cipher Suites: {}", rejected);
        return whiteList.toArray(new String[whiteList.size()]);
    }
}
Advertisements
Tagged ,

14 thoughts on “Connecting to SSL server from Android with self signed certificate

  1. Nicolas says:

    Hi,

    Your code is exactly what I search since some weeks !
    But, the class “SSLUtils” with the method “getCipherSuitesWhiteList”, I don’t found this class anything with this specified method.

    What is this class ? could you deal this class or send me download URL ?

  2. assylias says:

    I have added the code of SSLUtils, although you could also remove the line that uses it.

    • Nicolas says:

      Wonderful !

      This line permit to allow only THE certificate that I want ?
      If I remove, any verification is made (If I correctly understood)

      Can I check If the CN, or other values of my certificate are what I want in this specified sslUtils class ?)

      • assylias says:

        The cipher suite is basically the protocol used for the secured transaction (including the encryption algorithm). There are many of them and some are less secure which is why I exclude them. It has nothing to do with your certificate. That line simply prevents the server from using unsecure methods – but if you control the server you can simply remove that line.

      • Nicolas says:

        Ok !

        Thank you for this article and for theses comments 😉

  3. nybras says:

    I don’t understand the start of this Article.. “Download.” Download what exactly?

  4. Andreas Rueckert says:

    Where do you verify the certificate? I’ve seen this verification via HttpsURLConnection.getDefaultHostnameVerifier(); but it seems you don’t do this?

    Pardon my ignorance…

    • assylias says:

      I would have thought that TrustManagerFactory handles that. But not sure to be honest.

      • Ryan Amaral says:

        Hi, I would like to add the following information:

        “Caution: SSLSocket does not perform hostname verification. It is up the your app to do its own hostname verification, preferably by calling getDefaultHostnameVerifier() with the expected hostname. Further beware that HostnameVerifier.verify() doesn’t throw an exception on error but instead returns a boolean result that you must explicitly check.”

        source: https://developer.android.com/training/articles/security-ssl.html

  5. Bill says:

    I have a problem with this line:

    InputStream trustStoreStream = context.getResources().openRawResource(R.raw.server);

    Where do I take context? What does it mean?

    I apologize if the question is rookie but I just started programming on Android: D

  6. Baser Guvenc says:

    When i extract apk ,i can see *.bks file. Should i obfuscate it? Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: