title: How to get Trust anchors to work properly on Android API levels 16-19
body: <p>I am working on a project that has to support back to API level 16 and requires me to make network calls to dynamic URLs. The issue I am having is that the server recently had to update the TLS to 1.2 for PCI compliance, which by default is disabled on Android API 16-19. While enabling this is not difficult, I am running into an issue with X509 Certificates for those API levels only. </p>
  
  <p>I have done quite a bit of research on it and while all these links were useful:</p>
  
  <p>1) <a href="https://stackoverflow.com/questions/28943660/how-to-enable-tls-1-2-support-in-an-android-application-running-on-android-4-1">How to enable TLS 1.2 support in an Android application (running on Android 4.1 JB)</a></p>
  
  <p>2) <a href="https://stackoverflow.com/questions/47410689/how-to-use-a-self-signed-certificate-to-connect-to-a-mqtt-server-in-android-pah">How to use a self signed certificate to connect to a Mqtt server in Android (paho client)?</a></p>
  
  <p>3) <a href="https://stackoverflow.com/questions/9921548/sslsocketfactory-in-java">SSLSocketFactory in java</a></p>
  
  <p>4) <a href="https://stackoverflow.com/questions/1201048/allowing-java-to-use-an-untrusted-certificate-for-ssl-https-connection">Allowing Java to use an untrusted certificate for SSL/HTTPS connection</a></p>
  
  <p>5) <a href="https://stackoverflow.com/questions/6825226/trust-anchor-not-found-for-android-ssl-connection">Trust Anchor not found for Android SSL Connection</a></p>
  
  <p>6) <a href="https://stackoverflow.com/questions/36472463/sslhandshakeexception-trust-anchor-for-certification-path-not-found-only-on-an">SSLHandshakeException: Trust anchor for certification path not found. Only on Android API &lt; 19</a></p>
  
  <p>7) <a href="https://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https/6378872#6378872">Trusting all certificates using HttpClient over HTTPS</a></p>
  
  <p>They don't solve the core issue I have which is that I see this exception:</p>
  
  <pre><code> com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
       at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:151)
       at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)
   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:409)
       at com.android.okhttp.Connection.upgradeToTls(Connection.java:146)
       at com.android.okhttp.Connection.connect(Connection.java:107)
       at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
       at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
       at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
       at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
       at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
       at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)
       at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:136)
       at com.android.volley.toolbox.HurlStack.performRequest(HurlStack.java:110)
       at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96)
      ... 1 more
  </code></pre>
  
  <p>When I attempt to connect to a URL that requires TLS1.2 such as <a href="https://www.ssllabs.com/ssltest/viewMyClient.html" rel="noreferrer">https://www.ssllabs.com/ssltest/viewMyClient.html</a>.</p>
  
  <p>Essentially, it comes down to an issue with the TrustManager. </p>
  
  <p>Here are 2 different ways to get the TrustManager object (The first being more secure than the second as the second trusts all certs, which makes SSL a moot point):</p>
  
  <p>First Method: </p>
  
  <pre><code>TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
          TrustManagerFactory.getDefaultAlgorithm());
  trustManagerFactory.init((KeyStore) null);
  TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
  X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
  </code></pre>
  
  <p>Second Method:</p>
  
  <pre><code>X509TrustManager trustManager = new X509TrustManager() {
      public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {}
      public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {}
      public X509Certificate[] getAcceptedIssuers() {
          return null;
      }
  };
  </code></pre>
  
  <p>They are then used with this code:</p>
  
  <pre><code>SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
  sslContext.init(null, new TrustManager[] { trustManager }, null);
  HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
  </code></pre>
  
  <p>If I use the first TrustManager on API levels 20+, the url listed above will work just fine and the page will load. If I use the first on API levels 16-19, it will throw the exception listed above. </p>
  
  <p>If I use the second TrustManager on any API level 16+, the call will work, but, it leaves a security gap in my application because I am now trusting all certificates and leave myself open to all kinds of attacks. </p>
  
  <p>One other note here is that while the above sample error is from the Volley library, it still happens while using Retrofit with the same results.</p>
  
  <p>My question therefore is, how do I Utilize the X509TrustManager to work with websites like <a href="https://www.ssllabs.com/ssltest/viewMyClient.html" rel="noreferrer">This One</a> on API levels 16-19 like they do on API levels 20+?</p>
  
  <p>Thanks for your time.</p>