I am answering to this to give an idea about the scenario and solution as per the android developer site for others benefit. I have solved this using custom trust manager.
The problem was with the server certificate, it misses intermediate certificate authority. However with the first flow certificate path is completed somehow and result was successful certificate path validation.
There is a solution for this in android developer site. it suggest to use custom trust manager that trusts this server certificate or it suggest to server to include the intermediate CA in the server chain.
custom trust manager. source: https://developer.android.com/training/articles/security-ssl.html#UnknownCa
// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
// Tell the okhttp to use a SocketFactory from our SSLContext
OkHttpClient okHttpClient client = new OkHttpClient.Builder().sslSocketFactory(context.getSocketFactory()).build();
UPDATE: My problem was solved after intermediate certificate authority added to the certificate chain from the server side. It is the best solution, Bundling the certificate with the app requires app to be updated on certificate expiring or any other issues related with certificate management.
UPDATE:03/09/2017 Easiest way to load certificate file I found is use of raw resource.
InputStream caInput = new BufferedInputStream(context
.getResources().openRawResource(R.raw.certfilename));
where certfilename is the certificate file placed in resources/raw folder. Also okhttp’s sslSocketFactory(SSLSocketFactory sslSocketFactory)
has been deprecated and suggested approach in the okhttp api doc can be used.
Also when getting the certificate from the server it is better to use openssl.
openssl s_client -connect {server-address}:{port} -showcerts
Because I used to grab that from firefox and faced situation where it was altered by the virus guard.
Hii Developer in these Android solutions we have to solve the java security cert CertPathValidatorException API SSL Handshake Exception. Android volley error: “Trust anchor for certification path not found”, only in a real device, not an emulator. When you hit an API for the response they give you an error like this Android java.security.cert.CertPathValidatorException: Trust anchor for the certification path. you can get codeplayno Linkedin solution also.
java security cert CertPathValidatorException.
- java security cert CertPathValidatorException.
- how to solve java security cert CertPathValidatorException.
- How to Solve javax net SSL SSLHandshakeException.
- java.security.cert.certpathvalidatorexception in android.
- java security cert CertPathValidatorException Trust anchor for certification path.
- Android – Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
- java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. Android 2.3.
- javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Just Follow These Simple Steps for the Solution.
Step 1: Create a HttpsTrustManager
class that implements X509TrustManager
:
public class HttpsTrustManager implements X509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new HttpsTrustManager()};
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());
}
}
Step 2: Add HttpsTrustManager.allowAllSSL()
before you make an HTTPS request:
HttpsTrustManager.allowAllSSL();
Also, You can Learn More about Android solutions and Tutorials here:- Android Soltuon
Recently I was working on a chat application for the android platform, everything regarding the remote/networking implementation worked flawlessly. I used the Retrofit networking library and socket.io. At the time, the base url was without SSL (that is the HTTP scheme — http://api.example.com)
Just before we rolled out the MVP for beta testing, we acquired a domain name and enabled SSL on the server. This meant the base URL scheme became HTTPS (e.g https://api.example.com).
The change on the app to use a secured URL broke the entire app. All the endpoints were not connecting to the server successfully. Basically the network handshake process between the client and server wasn’t successful. Below is what the the error on the log was like
<-- HTTP FAILED: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Enter fullscreen mode
Exit fullscreen mode
After doing a little research I discovered it was an issue with the server certificate not being trusted by the android system. This could be because of any of the reasons below:
-
The Certificate Authority (CA) that issued the server certificate was unknown.
-
The server certificate wasn’t signed by a CA, but was self signed.
-
The server configuration is missing an intermediate CA.
In my case, this issue existed because the server certificate was self signed.
From android documentation there is a clean way to configure the app to trust your own self-signed certificates, which I will outline in 3 steps.
Step 1
Add the crt file to the raw folder.
This file will be retrieved from the server. You can request for the digital certificate from the backend engineer. It should come in a .crt extension.
Step 2
Create an XML network security config file (network_security_config.xml) like below:
network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">api.example.com</domain>
<trust-anchors>
<certificates src="@raw/certificate" />
</trust-anchors>
</domain-config>
</network-security-config>
Enter fullscreen mode
Exit fullscreen mode
Step 3
Specify the network configuration settings in the Manifest.xml
file of your application.
With these 3 steps done, you should connect seamlessly with the backend without any further issues.
Hi Paul,
I’m experiencing a problem when invoking HttpClient.PostAsync(). I’ve tried the call from 2 Android devices (Nexus 10 KitKat & Samsung Galaxy Tablet) and in both cases I get an exception with the call stack below [1].
At first I thought it was perhaps a problem with the server certificate not being installed correctly, but I have since eliminated that by checking it with the CA via their online tool (https://www.digicert.com/help/) and the final statement on the report generated is: «Congratulations! This certificate is correctly installed.»
I also checked the security settings on the Android device to make sure the root certificate for DigiCert is installed and has the checkbox tick, which it is on both accounts (the cert is found under the system certificates)
Do you have any suggestions for what else I might check?
Steve
[1]
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:430)
at com.squareup.okhttp.Connection.upgradeToTls(Connection.java:242)
at com.squareup.okhttp.Connection.connect(Connection.java:159)
at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:175)
at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:120)
at com.squareup.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:330)
at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:319)
at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:241)
at com.squareup.okhttp.Call.getResponse(Call.java:271)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:228)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:199)
at com.squareup.okhttp.Call.access$100(Call.java:34)
at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:162)
at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:282)
at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:202)
at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:663)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:426)
… 16 more
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.