OkHttp: SSLPeerUnverifiedException Failed to find a trusted cert that signed X.509 Certificate
<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>