Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found

I am using Retrofit to access my REST API. However, when I put my API behind ssl and access it by http://myhost/myapi then I get this error:

Do I need to do something extra now that my API is behind SSL?

Here is how I connect:

private final String API = "https://myhost/myapi";  private final RestAdapter REST_ADAPTER = new RestAdapter.Builder()         .setServer(API)         .setLogLevel(RestAdapter.LogLevel.FULL)         .build();  01-10 09:49:55.621    2076-2100/com.myapp.mobile D/Retrofit﹕ javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.             at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:401)             at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)             at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)             at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)             at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)             at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)             at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)             at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)             at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)             at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:90)             at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:48)             at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:287)             at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:222)             at $Proxy12.signin(Native Method)             at com.myapp.loginactivity$3.doInBackground(LoginActivity.java:143)             at com.myapp.loginactivity$3.doInBackground(LoginActivity.java:136)             at android.os.AsyncTask$2.call(AsyncTask.java:287)             at java.util.concurrent.FutureTask.run(FutureTask.java:234)             at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)             at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)             at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)             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 org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:282)             at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:202)             at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:595)             at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)             at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:398)             at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)             at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)             at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)             at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)             at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)             at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)             at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)             at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)             at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:90)             at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:48)             at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:287)             at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:222)             at $Proxy12.signin(Native Method)             at com.myapp.LoginActivity$3.doInBackground(LoginActivity.java:143)             at com.myapp.LoginActivity$3.doInBackground(LoginActivity.java:136)             at android.os.AsyncTask$2.call(AsyncTask.java:287)             at java.util.concurrent.FutureTask.run(FutureTask.java:234)             at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)             at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)             at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)             at java.lang.Thread.run(Thread.java:841) 
like image 596
birdy Avatar asked Jan 10 '14 14:01

birdy


People also ask

What does trust anchor for certification path not found mean?

Explanation: As for Android Java reference CertPathValidatorException: An exception indicating one of a variety of problems encountered when validating a certification path. The most usual problem is a self-signed certificate or a badly configured SSL web server.

What is a certificate trust anchor?

In a PKI, a trust anchor is a certification authority, which is represented by a certificate that is used to verify the signature on a certificate issued by that trust-anchor. The security of the validation process depends upon the authenticity and integrity of the trust anchor's certificate.


2 Answers

The reason this occur is the JVM/Dalvik haven't not confidence in the CA certificates in the system or in the user certificate stores.

To fix this with Retrofit, If you are used okhttp, with another client it's very similar.
You've to do:

A). Create a cert store contain public Key of CA. To do this you need to launch next script for *nix. You need openssl install in your machine, and download from https://www.bouncycastle.org/ the jar bcprov-jdk16-1.46.jar. Download this version not other, the version 1.5x is not compatible with android 4.0.4.

#!/bin/bash  if [ -z $1 ]; then   echo "Usage: cert2Android<CA cert PEM file>"   exit 1 fi  CACERT=$1 BCJAR=bcprov-jdk16-1.46.jar  TRUSTSTORE=mytruststore.bks ALIAS=`openssl x509 -inform PEM -subject_hash -noout -in $CACERT`  if [ -f $TRUSTSTORE ]; then     rm $TRUSTSTORE || exit 1 fi  echo "Adding certificate to $TRUSTSTORE..." keytool -import -v -trustcacerts -alias $ALIAS \       -file $CACERT \       -keystore $TRUSTSTORE -storetype BKS \       -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \       -providerpath $BCJAR \       -storepass secret  echo ""  echo "Added '$CACERT' with alias '$ALIAS' to $TRUSTSTORE..." 

B). Copy the file truststore mytruststore.bks in res/raw of your project truststore location

C). Setting SSLContext of the connection:

............. okHttpClient = new OkHttpClient(); try {     KeyStore ksTrust = KeyStore.getInstance("BKS");     InputStream instream = context.getResources().openRawResource(R.raw.mytruststore);     ksTrust.load(instream, "secret".toCharArray());      // TrustManager decides which certificate authorities to use.     TrustManagerFactory tmf = TrustManagerFactory         .getInstance(TrustManagerFactory.getDefaultAlgorithm());     tmf.init(ksTrust);     SSLContext sslContext = SSLContext.getInstance("TLS");     sslContext.init(null, tmf.getTrustManagers(), null);      okHttpClient.setSslSocketFactory(sslContext.getSocketFactory()); } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException e) {     e.printStackTrace(); } ................. 
like image 173
Fernando. Avatar answered Oct 11 '22 06:10

Fernando.


This can happen for several reasons, including:

  1. The CA that issued the server certificate was unknown
  2. The server certificate wasn't signed by a CA, but was self signed
  3. The server configuration is missing an intermediate CA

please check out this link for solution: https://developer.android.com/training/articles/security-ssl.html#CommonProblems

like image 20
Defuera Avatar answered Oct 11 '22 06:10

Defuera