Use Retrofit with a self-signed or unknown SSL certificate in Android

In this post I will highlight how to use Retrofit with a self-signed or unknown SSL certificate in Android

First of all, this is hell in a cell. took me 8 hours to accomplish this from the point of a working Service/API Manager that uses the Retrofit Rest Client for android.

 

retrofit-and-android

If you can avoid it, please don’t try this!

Android is Implicitly Secure

As opposed to iOS development, android does not work with self-signed SSL certificates and certificates where the Certificate Authority cannot be verified. Surprisingly, using an insecure SSL certificate works with iOS development (emulator and phone dev).

When using retrofit (verbose logging enabled) with the following code sample:


public static final RestAdapter REST_ADAPTER = new RestAdapter.Builder()
            .setEndpoint("https://my-unsecure-endpoint.co.za")
            .setClient(new OkClient(SplashActivity.trustTestClient))
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .setLog(new AndroidLog("RETROFIT"))
            .build();

We get the following error in Logcat:


java.security.cert.certificateexception: java.security.cert.certpathvalidatorexception: trust anchor for certification path not found.

Searching for this error and avoiding non-authentic sources we get:

Android Developer Docs Security with HTTPS and SSL – An excellent article explaining what is going on. Try the code yourself before moving on.

who-knows-maybe-you-can-break-the-bank-whoops

Go ahead use the Android Developer docs. Who knows maybe you can break the bank…whoops!

First of all this line of code…error prone for me. Do you need to change permissions or what?

InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));

Also who in their right mind will use the standard AndroidHttpClient,DefaultHttpClient or the HttpURLConnection. U WOT MATE? If you aren’t using Retrofit as your REST Client for Android Development either you haven’t found it or you are an idiot.

not using Retrofit REST Client

Not using Retrofit?

Let us get this self-signed or untrusted certificate

Lets get the certificate, we need the .pem.

A .pem is a container format that may include just the public certificate (such as with Apache installs, and CA certificate files /etc/ssl/certs), or may include an entire certificate chain including public key, private key, and root certificates. The name is from Privacy Enhanced Email, a failed method for secure email but the container format it used lives on, and is a base64 translation of the x509 ASN.1 keys.

Replace ${MY_SERVER} with the host name of the server you are using. Code below to acquire the SSL certificate PEM was provided by Crazy Bob.

echo | openssl s_client -connect ${MY_SERVER}:443 2>&1 | \sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > mycert.pem

Now we need to create a keystore (BKS) for the self-signed/untrusted certificate

Info on Keytool.

First of all we need to use Bouncy Castle, because android supports it. Poignantly the only version of the keystore creator jar that works is version 146. Download the required Jar.

Generate the keystore (BKS), use the above .pem as the -file:

keytool -import -v -trustcacerts -alias  -file mycert.pem -keystore mykeystore.bks -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath /home/odin/Downloads/bcprov-jdk15on-146.jar -storepass secret

Adding the Keystore to your Android Project

Copy your file to your android project directory in:src/main/res/raw/.

Load the Self Signed Certificate

Now you have a choice here, if you are nuts you can use the DefaultHttpClient highlighted on Codeproject or use the OkHttpClient by Square, the same creators and maintainers of Retrofit. To help you make your decision take a look at this post on github.

Below is the code for implementing the OkHttpClient Solution MySSLTrust.java class:


public class MySSLTrust {
    public static OkHttpClient trustcert(Context context){
        OkHttpClient okHttpClient = new OkHttpClient();
        try {
            KeyStore ksTrust = KeyStore.getInstance("BKS");
            InputStream instream = context.getResources().openRawResource(R.raw.mykeystore);
            ksTrust.load(instream, "secret".toCharArray());

            // TrustManager decides which certificate authorities to use.
            TrustManagerFactory tmf = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(ksTrust);
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), null);

            okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
        } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException e) {
            e.printStackTrace();
        }
        return okHttpClient;
    }
}

Now we to create this Client and make sure that retrofit uses it. But where to create this Client. To be honest I am not sure, but in my project I have a Starting Activity and I have made sure that the variable is public static

Linking the newly created certificate authority entrenched OkHttpClient with Retrofit

In StartingActivity.java:


//Class Atributes
public static OkHttpClient trustTestClient;

protected void onCreate(Bundle savedInstanceState) {
...
trustTestClient = MySSLTrust.trustcert(this);

Now we need to parse it to our ApiManager.java class which allows us to re-use the same Retrofit REST client throughout the application:

In short:


public static final RestAdapter REST_ADAPTER = new RestAdapter.Builder()
.setRequestInterceptor(intercept)
.setEndpoint("https://my-unsecure-endpoint.co.za")
.setClient(new OkClient(StartingActivity.trustTestClient))
.setLogLevel(RestAdapter.LogLevel.FULL)
.setLog(new AndroidLog("RETROFIT"))
.build();

The full ApiManager.java can be found at the end of this post.

So there we have it, quite a headache, I hope this saves you some time. Now we can use retrofit with a self-signed or unknown SSL certificate in Android.
Any comments or ways to improve the code always welcome, please comment below.

android-https-ssl-certificate

I struggled with this one, but at the end of the day…

ApiManager.java:


public class ApiManager {

    public interface MyAPI {
        @GET("/path")
        public void voyager(@Query("var1") String var1, @Query("var2") String var2,
                            Callback response);
    }

    private static final String ENDPOINT = "https://my-unsecure-endpoint.co.za";

    //Member of Retrofit Library - creates adapter object
    //TODO: Remove Debugging during QA phase
    public static final RestAdapter REST_ADAPTER = new RestAdapter.Builder()
            .setEndpoint(ENDPOINT)
            .setClient(new OkClient(StartingActivity.trustTestClient))
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .setLog(new AndroidLog("RETROFIT"))
            .build();

    private static final MyAPI MYAPI = REST_ADAPTER.create(MyAPI.class);

    public static MyAPI getService() {
        return MYAPI;
    }
}

How to ace a PHP job test in South Africa

Initial Preparation

First of all do a project in PHP that utilises the database. I am talking about pure PHP and not a framework. Remember to turn make sure you set the following configuration settings.


display_errors = 1;
error_reporting(E_ALL);

You can always view the php documentation which is always of great help.

 Get ready for some specialised questions

The off-the-wall questions

  • What do you think of garden gnomes? Your answer should include some form of analysis and deduction.
  • Why are man-hole covers a circle? The answer is because it is not possible for the cover to fall into the hole that way.

PHP Specific Questions

Increment and Decrement Operators

Example Name Effect
++$a Pre-increment Increments $a by one, then returns $a.
$a++ Post-increment Returns $a, then increments $a by one.
–$a Pre-decrement Decrements $a by one, then returns $a.
$a– Post-decrement Returns $a, then decrements $a by one.

Question 1: ++$a * $a++ + $a = ? (Where $a = 5)

Answer 1: 6 * 5 + 5 = 35

Bitwise Operators

Example Name Result
$a & $b And Bits that are set in both $a and $b are set.
$a | $b Or (inclusive or) Bits that are set in either $a or $b are set.
$a ^ $b Xor (exclusive or) Bits that are set in $a or $b but not both are set.
~ $a Not Bits that are set in $a are not set, and vice versa.
$a << $b Shift left Shift the bits of $a $b steps to the left (each step means “multiply by two”)
$a >> $b Shift right Shift the bits of $a $b steps to the right (each step means “divide by two”)

Question 2: echo 5 & 7;

Answer 2:

5 = 0101
7 = 0111

Now AND the bits

Answer = 0101 (5)

Question 3: echo 12 ^ 9;

Answer 3:

12 = 1100
9  = 1001
Now XOR the bits
Answer = 0101 (5)

Question 4:$x = 5; echo $x >> 2;
Answer 4:


5 = 0101
Shift bits 2 steps to the right

Answer = 0001 (1)

Learn some functions of the PHP library

array_shift  – Shifts an element off the beginning of an array

array_combine – Creates an associative array by using 1 for keys and 1 for values

final keyword – Prevents overriding and extension of the class

interfaces – Interfaces specify which methods a class must implement, but does not specify the code for the methods.

suppression of errors

Learn some permutations, combinations and factorial

I’m not good at these and if anyone has a tutorial or content to add please free to comment.

Here are some resources that may help, if you find out how to do these please comment below.

Circular Permutations

Example Permutation and Combination Question

Maths is Fun

If ABCDEFGH are sitting at a table, where the configuration of the seats is 1 at each head of the table, and 3 on either side. If A can’t sit next to B and F can’t sit G, how many different configurations are there?

How many different numberplates can be made, if the numberplate must contain only digits and no signle digit can be repeated if there are 5 spaces for digits on the numberplate?

Please leave comments if you have anything else to add.

PHP job test