androidgoogle-app-enginegoogle-cloud-endpointspinningpublic-key-pinning

Implementing SSL pinning using Trustkit with Google Cloud Endpoints


I am using Google Cloud Endpoints to interact with the app engine backend for my Android app. I want to implement public key/SSL pinning. It's easy to do this for Android N and above, but i want to implement pinning for earlier versions of Android. It seems like a common way to do this is using Trustkit.

The Getting Started notes on the Trustkit link, describe how to set it up by setting the SSLSocketFactory, for example

  // HttpsUrlConnection
  HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
  connection.setSSLSocketFactory(TrustKit.getInstance().getSSLSocketFactory(serverHostname));

  // OkHttp 2.x
  OkHttpClient client =
    new OkHttpClient()
        .setSSLSocketFactory(TrustKit.getInstance().getSSLSocketFactory(serverHostname));

But i'm not sure how to apply this to Google Cloud Endpoints because of the way the connection is set up, for example here's how its set up for Google Cloud Endpoints in my code

        import com.xxxx.backend.myApi.MyApi;
    
    //I believe the MyApi class is generated automatically as part of the Google Cloud Endpoints integration in Android Studio.
        
        class EndpointsAsyncTask  extends AsyncTask<HashMap, Void, String> {
        
        @Override
        protected String doInBackground(HashMap... params) {

        HashMap<String, String> dict = params[0];
        String data = dict.get("dataString");

        
         MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
                                .setRootUrl("https://xxxxx").setApplicationName("xxxx");
        
        myApiService = builder.build();
        
        //This calls the API method
        return myApiService.customApiMethodName(data).execute().getDict().toString();
        }
        }

What I want to find out is how i can I implement SSL pinning in early versions of Android e.g. API16-API23 while still connecting to Google Cloud Endpoints in the same way my App does as shown above?

If possible i'd like to use Trustkit, maybe there is a different way i can set up how to connect with my Api methods so i can use it? If this is not possible is there an alternative to Trustkit i can use? or just a completely different way to implement SSL pinning while still using Google Cloud Endpoints in this way?


Solution

  • You would have to stop using the AndroidHttp helper and write your own, based off of it.

    Instead of just calling new NetHttpTransport() or new ApacheHttpTransport(), you must use their builders instead, for example:

    public static HttpTransport newCompatibleTransport(String hostname) {
      SSLSocketFactory factory = TrustKit.getInstance().getSSLSocketFactory(serverHostname);
      if (AndroidUtils.isMinimumSdkLevel(9)) {
        return new NetHttpTransport.Builder()
            .setSslSocketFactory(factory)
            .build();
      }
      return new ApacheHttpTransport.Builder()
          .setSslSocketFactory(factory)
          .build();
    }