Dedicated Server
Showing posts with label SSLHandshake. Show all posts
Showing posts with label SSLHandshake. Show all posts

How to solve SSLHandshakeException in Android : SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version ?


Being android developers, we might have at least one time come across this issue >>

javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb8df4b50: Failure in SSL library, usually a protocol error
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0x8d92d990:0x00000000)

or sometimes a similar variant of the above issue. What this actually means is that >>
"The server you are talking to is supporting only a specific protocol version which your client(your android app) is unaware of. That is, your client does not support that particular version"
The issue is mostly encountered in devices below lollipop i.e, kitkat and below devices. Let us see why the issue occurs.

Example Case :

Try getting some response from the host https://api.github.com/ like shown below

Retrofit retrofit1 = new Retrofit.Builder()
                .baseUrl("https://api.github.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();


        GithubServise githubServise = retrofit1.create(GithubServise.class);

        Call<ResponseBody> call = githubServise.getGithub();
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                Toast.makeText(MainActivity.this, "got response" , Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Toast.makeText(MainActivity.this, "SSL error?" , Toast.LENGTH_SHORT).show();
            }
        });


GithubServise.java

public interface GithubServise {
    @GET("/users/{pass_any_github_username_here}/repos")
    Call<ResponseBody> getGithub();
}

pass your github username in the interface as shown so that you could fetch your repos

You could make the following  observations while running this :


  1. This code would run successfully without any issues from android api levels 20+(from lollipop onwards) and will fetch us a successful response with list of repos.
  2.  This will not return any successfull response in the case of android devices below 20(kitkat(19) and below). The onFailure method will be executed with an error like this
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb8df4b50: Failure in SSL library, usually a protocol errorerror:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0x8d92d990:0x00000000)
The reason why this is working only in devices with api levels 20+ is that the host  https://api.github.com/ supports only TLS 1.2 which is by default disabled in android devices below 20.

You can see the list of protocols supported by your web server by going here https://www.ssllabs.com/ssltest/ and typing in https://api.github.com/ inside hostname field.

check the list of protocols supported by the website

Certificate Pinning in Retrofit,Android using CertificatePinner

Usage Scenario :

We may have often connected our client side apps to a lot of web servers. We may build our apps this way easily, but how can we ensure that we are communicating with the right web servers that we actually intend to communicate with? What if we are accessing some malicious web servers thinking that it is actually our servers ? Now this is where https comes into role. Apart from putting a secure label in front of your url at the address bar, it actually does more. It actually adds a security layer where in all the communication between your client and web server are encrypted.

Now one way of making sure that you are connecting to an appropriate web server is by using a method called Certificate Pinning. The idea behind Certificate Pinning is that we actually pins the public key hash of a particular host within our client side app. So during SSL Handshake, we are actually checking if the public key hash matches with the web server that we are connecting to.

Note : One major disadvantage with Certificate Pinning is that we may need to update our app if the web server gets it certificate updated. That is we need to change the public key hash which is hardcoded in the app
You may find more details about retrofit ssl pinning by visiting here

So first thing we need is to get the public key hash of the host which we are trying to connect to. Suppose that our host is api.github.com. Then we may get its public key hash by the following method

First go to https://www.ssllabs.com/ssltest/ and type in api.github.com inside the hostname field and tap submit like shown below