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.