title: Certificate pinning not working with OkHttp on Android
body: <p>Using <code>com.squareup.okhttp:okhttp:2.4.0</code> with <code>com.squareup.retrofit:retrofit:1.9.0</code> on an Android app, trying to communicate with an server REST API over HTTPS, that uses a self signed certificate.</p>
  
  <p>Server keystore has a private key and 2 certificates, the server's and a root certificate. <code>openssl s_client</code> output - </p>
  
  <pre><code>Certificate chain
   0 s:/C=...OU=Dev/CN=example.com
     i:/C=... My CA/emailAddress=info@example.com
   1 s:/C=... My CA/emailAddress=info@example.com
     i:/C=... My CA/emailAddress=info@example.com
  </code></pre>
  
  <p>At the Android app, OkHttp is initialised with the root certificate's SHA1 signature -</p>
  
  <pre><code>CertificatePinner certificatePinner = new CertificatePinner.Builder()
          .add("example.com", "sha1/5d...3b=")
          .build();
  
  OkHttpClient client = new OkHttpClient();
  client.setCertificatePinner(certificatePinner);
  
  RestAdapter restAdapter = new RestAdapter.Builder()
          .setEndpoint("https://example.com")
          .setClient(new OkClient(client))
          .build();
  </code></pre>
  
  <p>But when trying to send a request fails with exception -</p>
  
  <pre><code>retrofit.RetrofitError: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
          at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:395)
          at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
          at java.lang.reflect.Proxy.invoke(Proxy.java:397)
          at $Proxy1.report(Unknown Source)
          ...
          at android.os.AsyncTask$2.call(AsyncTask.java:288)
          at java.util.concurrent.FutureTask.run(FutureTask.java:237)
          at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
          at java.lang.Thread.run(Thread.java:818)
   Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
          at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:306)
          at com.squareup.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:103)
          at com.squareup.okhttp.Connection.connect(Connection.java:143)
          at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:185)
          at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
          at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:341)
  </code></pre>
  
  <p>It's thrown at <code>com.squareup.okhttp.internal.http.SocketConnector</code> when trying <code>sslSocket.startHandshake()</code>, even before <code>CertificatePinner</code> is used to check the received certificates.</p>
  
  <p>I've made sure server has certificates installed correctly using <code>openssl</code> and with <code>curl --cacert root.pem</code>. </p>
  
  <p>So why does OkHttp throw an exception before even trying to check if provided certificates are OK? </p>