SSL Pinning using Google Volley
Asked Answered
L

1

13

I am starting my question by mentioning what I have tried so far:

I do not have certificate in my app, I am using SHA256 key only, Most of the answer on internet requires physical certificate in app to load it in keystore, I don't have that.

I am getting following error:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

1)TrustKit It need compile SDK 24 and up, but I have 23 and lots of Support library are in sync with SDK 23 so I can not change all of them, it may crash my app at some time.

2)CWAC-NetSecurity I have implemented this in my code without using Android N security setup, I have also followed instruction given on git page, but not able to pass sslSocketfactory to Volley from it, it has example with OkHTTP. so it is also giving above error.

I have tried this with OKHttp's CertificatePinner by it is also not working for me. Same error. I have also tried to pass hostNameVerifier and sslSocketFactory to HttpsUrlConnection but same error.

JsonObjectRequestSolaire jsonRequest = new JsonObjectRequestSolaire(method, URL, object, headers, responseListener, errorListener);
    RetryPolicy policy = new DefaultRetryPolicy(TIMEOUT, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
    jsonRequest.setRetryPolicy(policy);
    jsonRequest.setShouldCache(false);

    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .certificatePinner(new CertificatePinner.Builder()
                    .add("my_domain", "sha256/shaKey")//example.com
                    .add("my_domain", "sha256/shaKey")//also tried *.example.com
                    .build())
            .build();

    //HttpsURLConnection.setDefaultHostnameVerifier(okHttpClient.hostnameVerifier());
    //HttpsURLConnection.setDefaultSSLSocketFactory(okHttpClient.sslSocketFactory());

    RequestQueue requestQueue = Volley.newRequestQueue(activity.getApplicationContext(), new HurlStack(null, okHttpClient.sslSocketFactory()));
    requestQueue.add(jsonRequest);

by using trustKit our iOS guy implemented and it is working for him.

Thanks in Advance.

Please share your valuable input here, so that i can understand this SSL pinning concept.

Laconism answered 9/8, 2017 at 14:1 Comment(3)
Is the used server certificate valid? Pinning means regular certificate check + pinning of the root, intermediate or leave certificate. BTW: If you have the sha256 hash and the domain name you can simply download the certificate fro the server any verify if it is the correct one.Keishakeisling
Check this link also.Berner
Check this also, might be the problem with CA.Berner
D
5

Use this VolleySingleton:

public class VolleySingleton {


  private static VolleySingleton mInstance;
  private RequestQueue mRequestQueue;
  private static Context mCtx;

  private VolleySingleton(Context context) {
    mCtx = context;
    mRequestQueue = getRequestQueue();
  }

  public static synchronized VolleySingleton getInstance(Context context) {
    if (mInstance == null) {
      mInstance = new VolleySingleton(context);
    }
    return mInstance;
  }

  public RequestQueue getRequestQueue() {
    if (mRequestQueue == null) {
      // getApplicationContext() is key, it keeps you from leaking the
      // Activity or BroadcastReceiver if someone passes one in.
      mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext(), new HurlStack(null, newSslSocketFactory()));
    }
    return mRequestQueue;
  }

  public <T> void addToRequestQueue(Request<T> req) {
    int socketTimeout = 90000;
    RetryPolicy policy = new DefaultRetryPolicy(socketTimeout,
        DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
    req.setRetryPolicy(policy);
    getRequestQueue().add(req);
  }

  private SSLSocketFactory newSslSocketFactory() {
    try {
      // Get an instance of the Bouncy Castle KeyStore format
      KeyStore trusted = KeyStore.getInstance("BKS");
      // Get the raw resource, which contains the keystore with
      // your trusted certificates (root and any intermediate certs)
      InputStream in = mCtx.getApplicationContext().getResources().openRawResource(R.raw.trusted);
      try {
        // Initialize the keystore with the provided trusted certificates
        // Provide the password of the keystore
        trusted.load(in, mCtx.getString(R.string.KEYSTORE_PASS).toCharArray());
      } finally {
        in.close();
      }

      String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
      TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
      tmf.init(trusted);

      SSLContext context = SSLContext.getInstance("TLSv1.2");
      context.init(null, tmf.getTrustManagers(), null);

      HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
          Log.i("Volley","Verifing host:"+hostname);
          return true;
        }
      });

      SSLSocketFactory sf = context.getSocketFactory();
      return sf;
    } catch (Exception e) {
      throw new AssertionError(e);
    }
  }
}
Delogu answered 16/8, 2017 at 18:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.