title: OkHttp: SSLPeerUnverifiedException Failed to find a trusted cert that signed X.509 Certificate
body: <p>Actually, this week, I have the same question as the following </p>
  
  <blockquote>
    <p><a href="https://stackoverflow.com/questions/37772360/okhttpclient-and-certificate-authority-validation-in-android">OkHttpClient and Certificate Authority Validation in Android</a></p>
  </blockquote>
  
  <p>In my phone (Motorola, Android 4.1.2), I disable all DigiCert CAs (inside <code>Settings - Security - Trusted credentials - System</code>).</p>
  
  <p>My code below:</p>
  
  <pre><code>public class CertPinActivity extends AppCompatActivity {
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_cert_pin);
  
          try {
              CertificatePinner certificatePinner = new CertificatePinner.Builder()
                      .add("github.com", "sha256/WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=")
                      .build();
              OkHttpClient client = new OkHttpClient.Builder()
                      .sslSocketFactory(getSSLSocketFactory())
                      .certificatePinner(certificatePinner)
                      .build();
  
              Request request = new Request.Builder()
                      .url("https://github.com/square/okhttp/wiki/HTTPS")
                      .build();
              client.newCall(request).enqueue(new Callback() {
                  @Override
                  public void onFailure(Call call, IOException e) {
                      Log.e("onFailure","-------------------------------------------------");
                      e.printStackTrace();
                  }
  
                  @Override
                  public void onResponse(Call call, Response response) throws IOException {
                      Log.d("onResponse", response.body().string());
                  }
              });
          } catch (Exception e){
              e.printStackTrace();
          }
      }
  
      private SSLSocketFactory getSSLSocketFactory()
              throws CertificateException, KeyStoreException, IOException,
              NoSuchAlgorithmException, KeyManagementException {
          CertificateFactory cf = CertificateFactory.getInstance("X.509");
          InputStream caInput = getResources().openRawResource(R.raw.github); // this is exported from Chrome then stored inside \app\src\main\res\raw path
          Certificate ca = cf.generateCertificate(caInput);
          caInput.close();
          KeyStore keyStore = KeyStore.getInstance("BKS");
          keyStore.load(null, null);
          keyStore.setCertificateEntry("ca", ca);
          String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
          TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
          tmf.init(keyStore);
          SSLContext sslContext = SSLContext.getInstance("TLS");
          sslContext.init(null, tmf.getTrustManagers(), null);
          return sslContext.getSocketFactory();
      }
  }
  </code></pre>
  
  <p>My app got the following logcat (sorry I truncate because it's too long)</p>
  
  <pre><code>06-14 09:10:10.065 30176-30211/com.example.okhttps3 E/onFailure: -------------------------------------------------
  06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: javax.net.ssl.SSLPeerUnverifiedException: Failed to find a trusted cert that signed X.509 Certificate:
  06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: [
  06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err: [
  06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err:   Version: V3
  06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err:   Subject: CN=DigiCert SHA2 Extended Validation Server CA,OU=www.digicert.com,O=DigiCert Inc,C=US
  06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err:   Signature Algorithm: SHA256WithRSAEncryption, params unparsed, OID = 1.2.840.113549.1.1.11
  06-14 09:10:10.065 30176-30211/com.example.okhttps3 W/System.err:   Key: 
  ...................................................................................
  06-14 09:17:56.813 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.tls.CertificateChainCleaner$BasicCertificateChainCleaner.clean(CertificateChainCleaner.java:132)
  06-14 09:17:56.813 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.CertificatePinner.check(CertificatePinner.java:149)
  06-14 09:17:56.813 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.io.RealConnection.connectTls(RealConnection.java:252)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.io.RealConnection.establishProtocol(RealConnection.java:196)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:171)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.RealCall.getResponse(RealCall.java:243)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.RealCall.access$100(RealCall.java:30)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
  06-14 09:17:56.823 5934-5984/com.example.okhttps3 W/System.err:     at java.lang.Thread.run(Thread.java:856)
  </code></pre>
  
  <p>However, <code>onResponse</code> called in the following cases:</p>
  
  <ol>
  <li>Both <code>.sslSocketFactory(getSSLSocketFactory())</code> and <code>.certificatePinner(certificatePinner)</code> removed;</li>
  <li>Only <code>.sslSocketFactory(getSSLSocketFactory())</code> removed; (actually, with emulator, when system CA disabled, <code>onFailure</code> called and inside it <code>java.security.cert.CertPathValidatorException: Trust anchor for certification path not found</code> thrown)</li>
  <li>Only <code>.certificatePinner(certificatePinner)</code> removed.</li>
  </ol>
  
  <p>Logcat with <code>onResponse</code> as below (too long so I truncate):</p>
  
  <pre><code>06-14 09:06:23.143 26571-26616/com.example.okhttps3 D/onResponse: &lt;!DOCTYPE html&gt;
                                                                    &lt;html lang="en" class=""&gt;
                                                                    .....
  </code></pre>
  
  <p>So, my questions are:</p>
  
  <ol>
  <li>The same as the link at the beginning in my question (actually his 1st issue);</li>
  <li>Why does my app get <code>javax.net.ssl.SSLPeerUnverifiedException: Failed to find a trusted cert that signed X.509 Certificate</code> when <code>certificatePinner</code> used with <code>getSSLSocketFactory</code>? Please note that the inner message of this <code>SSLPeerUnverifiedException</code> is different from <code>Certificate pinning failure!</code> as mentioned in <a href="https://square.github.io/okhttp/2.x/okhttp/com/squareup/okhttp/CertificatePinner.html" rel="nofollow noreferrer">this JavaDoc</a>.</li>
  </ol>
  
  <hr>
  
  <p><strong>UPDATE:</strong></p>
  
  <p><em>For 1st issue:</em></p>
  
  <p>Looks like this issue (System/User Trusted credentials not effective) only happened in my phones which run Android 4.1.2, I have checked 02 devices, so I think I should contact the manufacturer.</p>
  
  <p><em>For 2nd issue:</em></p>
  
  <p>From the comment of @Robert below <code>"I assume you have to include the full certificate chain (or the root certificate if the server sends you the chain), not only the leave certificate"</code>, I have exported Root CA instead, as the following screenshot, although not completed chain, and inside <code>getSSLSocketFactory</code> I changed to <code>getResources().openRawResource(R.raw.github_rootca);</code></p>
  
  <p><strong>Now, my 2nd issue is solved!</strong> </p>
  
  <p><a href="https://i.stack.imgur.com/w1NZD.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/w1NZD.png" alt="enter image description here"></a></p>