java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. on api less 24

first you will need to generate your certificate file and here is the steps

  • go to your website link on Firefox browser

  • click on the green lock on the right of website link

  • click on more info then view certificate

  • a new window will appear with two taps general and details choose details

  • click on export to export your certificate and save this file in android project assets.

second in you project application class define hurlStack variable and use the next method in application OnCreate Method

 private void handleCertificationOnOlderDevices() {
    try {

        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = new 
                            BufferedInputStream(getAssets().open("porter_cert.crt"));
        Certificate ca;
        try {
            ca = cf.generateCertificate(caInput);
            Log.d("certificate", ((X509Certificate) ca).getSubjectDN().toString());
        } finally {
            caInput.close();
        }

        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

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

        TrustManager[] trustManagers = tmf.getTrustManagers();
        final X509TrustManager origTrustmanager =  
                                                (X509TrustManager) trustManagers[0];

        TrustManager[] wrappedTrustManagers = new TrustManager[]{
                new X509TrustManager() {
                   public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return origTrustmanager.getAcceptedIssuers();
                   }

                   public void checkClientTrusted(X509Certificate[] certs,  
                   String authType) 
                   {
                        try {
                            origTrustmanager.checkClientTrusted(certs, authType);
                        } catch (CertificateException e) {
                            e.printStackTrace();
                        }
                    }

                    public void checkServerTrusted(X509Certificate[] certs,
                    String authType) 
                    {
                        try {
                            origTrustmanager.checkServerTrusted(certs, authType);
                        } catch (CertificateException e) {
                            e.printStackTrace();
                        }
                    }
                }
        };

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

        SSLSocketFactory sslSocketFactory = context.getSocketFactory();
        hurlStack = new HurlStack(null, sslSocketFactory);

    } catch (Exception e) {
        e.printStackTrace();
    }

}

and on volley requestQueue use hurlStack

    public RequestQueue getRequestQueue() {
       if (requestQueue == null)
           requestQueue = Volley.newRequestQueue(getApplicationContext(), 
           hurlStack);
       return requestQueue;
    }

third if you use Glide for images you will got a second error with ssl certificate related to glide and you will need to solve it by this way

1 - update in app build your gilde and okhttp3 to these version

    implementation "com.squareup.okhttp3:okhttp:3.8.1"
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
    implementation ('com.github.bumptech.glide:okhttp3-integration:4.9.0'){
    exclude group: 'glide-parent'
    }

2 - add the next class to your project

@GlideModule 
public class CustomGlideModule extends AppGlideModule {
   @Override
   public void registerComponents(Context context, Glide glide,  
   Registryregistry) {
      if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N) {
          OkHttpClient client = 
                        SafeOkHttpClient.getSafeOkHttpClient(context);
          OkHttpUrlLoader.Factory factory = new 
                                       OkHttpUrlLoader.Factory(client);
          glide.getRegistry().replace(GlideUrl.class, InputStream.class, 
          factory);
      }
   }

 }

and now glide will work fine with you.


What is the TLS version on your server? Most likely it is 1.2 or higher. For kitkat devices, 1.2 is off by default and needs to be enabled. If your devices have Google play services you can do this via that. Otherwise you need a custom socket factory class which specifies 1.2 and probably 1.3.

If it is lower than 1.2, post Kitkat devices will not permit connections unless you trust all certs with the hack in your question. It should not be lower.