Trust anchor for certification path not found как исправить

There are three hosts that an android app do the authentication and authorization. Final host is the REST API. For the first time using Oauth authentication and authorization process it works without

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 

Enya Emmanuel

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:

  1. The Certificate Authority (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.

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.

crt file

Step 2

Create an XML network security config file (network_security_config.xml) like below:

XML network security config file

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.

android manifest file

With these 3 steps done, you should connect seamlessly with the backend without any further issues.

@hasnabbas

Browsers and versions affected
Android native app

Description
All devices with my app installed on them are getting same error. Previously, I was getting the recent issue, /issues/585 (apprtc expired certificate). Now that that issue seems to be fixed, and now I am starting to get this one.

Steps to reproduce
Running the same app that worked previously

Expected results
Should initiate chat between two peers.

Actual results
Connection Error: HTTP POST to https://appr.tc/join/9f48fcc6-30e0-47f2-ba35-f6cb8da19a7b error: ja
va.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

@maxvuluy

@hasnabbas

@maxvuluy

Open https://appr.tc with a browser.
Click the lock icon, then you can see the detail of certification.
You can find the url to download the certification file somewhere (depend on browser).
I’m not sure, but I think it is.

I will try this way later.
If you tried, please let me know the result.
Thank you.

@elixiroflife4u

+1 for this issue. I am also getting «Trust anchor for certification path not found» when attempting any kind of call from AppRTC Android demo app (approx release 63 and rel 68). The same app on same android device had worked till around October 30.

@maxvuluy

The solution @HasnainAD mentioned worked.

  1. Download certification file and put in asset of android project.
  2. Run the following code to make android trust this certification.
httpsURLConnection.setSSLSocketFactory(trustCert().getSocketFactory());

private SSLContext trustCert() throws CertificateException,IOException,KeyStoreException,
	NoSuchAlgorithmException,KeyManagementException {
	AssetManager assetManager = getAssets();
	CertificateFactory cf = CertificateFactory.getInstance("X.509");
	Certificate ca = cf.generateCertificate(assetManager.open("COMODORSADomainValidationSecureServerCA.crt"));

	// 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);
	return context;
}

But I think it’s just a compromise solution for those who cannot wait.
The ultimate way is the server need to correct it to make certification work on android.

@devedgarKim

The solution @HasnainAD mentioned worked.

  1. Download certification file and put in asset of android project.
  2. Run the following code to make android trust this certification.
httpsURLConnection.setSSLSocketFactory(trustCert().getSocketFactory());

private SSLContext trustCert() throws CertificateException,IOException,KeyStoreException,
	NoSuchAlgorithmException,KeyManagementException {
	AssetManager assetManager = getAssets();
	CertificateFactory cf = CertificateFactory.getInstance("X.509");
	Certificate ca = cf.generateCertificate(assetManager.open("COMODORSADomainValidationSecureServerCA.crt"));

	// 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);
	return context;
}

But I think it’s just a compromise solution for those who cannot wait.
The ultimate way is the server need to correct it to make certification work on android.

great it working well

@hasnabbas

The solution @HasnainAD mentioned worked.

  1. Download certification file and put in asset of android project.
  2. Run the following code to make android trust this certification.
httpsURLConnection.setSSLSocketFactory(trustCert().getSocketFactory());

private SSLContext trustCert() throws CertificateException,IOException,KeyStoreException,
	NoSuchAlgorithmException,KeyManagementException {
	AssetManager assetManager = getAssets();
	CertificateFactory cf = CertificateFactory.getInstance("X.509");
	Certificate ca = cf.generateCertificate(assetManager.open("COMODORSADomainValidationSecureServerCA.crt"));

	// 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);
	return context;
}

But I think it’s just a compromise solution for those who cannot wait.
The ultimate way is the server need to correct it to make certification work on android.

Hey max, thanks for the code, do I need to run it one time per session or everytime before starting a call?

@remyasics

httpsURLConnection.setSSLSocketFactory(trustCert().getSocketFactory());
where should I add this line of code.I am using AsyncHttpURLConnection in my code

@hasnabbas

@maxvuluy

@HasnainAD
trustCert() only called once, then you can use the produced SSLContext multiple times.

@remyasics

private void sendHttpMessage() {
    try {
      HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
      ...
      if (connection instanceof HttpsURLConnection) {
        ((HttpsURLConnection) connection).setSSLSocketFactory(sslContext.getSocketFactory());
      }
      ...
      // Get response.
      int responseCode = connection.getResponseCode();
      ...
    } catch (SocketTimeoutException e) {
      events.onHttpError("HTTP " + method + " to " + url + " timeout");
    } catch (IOException e) {
      events.onHttpError("HTTP " + method + " to " + url + " error: " + e.getMessage());
    }
  }

@hasnabbas

@maxvuluy how to use it with AsyncHttpURLConnection?

Following is my code:

 httpConnection =
                new AsyncHttpURLConnection("POST", roomUrl, roomMessage, new AsyncHttpEvents() {
                    @Override
                    public void onHttpError(String errorMessage) {
                        Log.e(TAG, "Room connection error: " + errorMessage);
                        events.onSignalingParametersError(errorMessage);
                    }

                    @Override
                    public void onHttpComplete(String response) {
                        roomHttpResponseParse(response);
                    }
                });
        httpConnection.send();

@remyasics

@remyasics

private void sendHttpMessage() {
    try {
      HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
      ...
      if (connection instanceof HttpsURLConnection) {
        ((HttpsURLConnection) connection).setSSLSocketFactory(sslContext.getSocketFactory());
      }
      ...
      // Get response.
      int responseCode = connection.getResponseCode();
      ...
    } catch (SocketTimeoutException e) {
      events.onHttpError("HTTP " + method + " to " + url + " timeout");
    } catch (IOException e) {
      events.onHttpError("HTTP " + method + " to " + url + " error: " + e.getMessage());
    }
  }

Thank you

@remyasics

AssetManager assetManager = getAssets();

is giving me error

@maxvuluy

@HasnainAD I modified AsyncHttpURLConnection as below
@remyasics I’m sorry. getAssets() is a function of Context.
You can put turstCert() in a Activity.

public class AsyncHttpURLConnection {
    private static SSLContext sslContext;

    public static setSSLContext(SSLContext sslContext) {
        this.sslContext = sslContext;
    }

    private void sendHttpMessage() {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            ...
            if (connection instanceof HttpsURLConnection) {
                ((HttpsURLConnection) connection).setSSLSocketFactory(sslContext.getSocketFactory());
            }
            ...
            // Get response.
            int responseCode = connection.getResponseCode();
            ...
        }
    }
}

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onResume() {
        super.onResume();
        try {
            AsyncHttpURLConnection.setSSLContext(trustCert());
        } catch (CertificateException | IOException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
            e.printStackTrace();
        }
    }

    private SSLContext trustCert() throws CertificateException,IOException,KeyStoreException,NoSuchAlgorithmException,KeyManagementException {
        AssetManager assetManager = getAssets();
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        Certificate ca = cf.generateCertificate(assetManager.open("COMODORSADomainValidationSecureServerCA.crt"));

        // 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);
        return context;
    }
}

@hasnabbas

👍 @maxvuluy Thanks a lot man! I got it working.

@remyasics

@remyasics

I think since it has certificate verification we can use it for production also.Any idea?

@maxvuluy

I thought this issue is not completely solved.
I use openssl to trace certificate chain of appr.tc

openssl s_client -connect appr.tc:443 -servername appr.tc
---
Certificate chain
 0 s:/OU=Domain Control Validated/OU=PositiveSSL/CN=appr.tc
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Domain Validation Secure Server CA
---

According to COMODO’s explanation and android guide, the certificate chain of server seems to be incomplete.
Is there any member of WebRTC can help confirm this issue?

The solution with TrustManager is just a compromise. I don’t think it’s a good solution.
It would be great if manager of appr.tc could help solve this issue.
@HasnainAD could you help re-open this issue? Thanks.

@einsteinarbert

Does appr.tc website error cert? Because I don’t think project error, because my code not update for along and when I come back, this error suddenly appear

@valon91

httpsURLConnection.setSSLSocketFactory(trustCert().getSocketFactory());

where to write this code, how to call it? I am using volley for parsing JSON , please help

@vj12354

This was referenced

Jan 12, 2021

DISCLAIMER: this answer is from Jul 2015 and uses Retrofit and OkHttp from that time.
Check this link for more info on Retrofit v2 and this one for the current OkHttp methods.

Okay, I got it working using Android Developers guide.

Just as OP, I’m trying to use Retrofit and OkHttp to connect to a self-signed SSL-enabled server.

Here’s the code that got things working (I’ve removed the try/catch blocks):

public static RestAdapter createAdapter(Context context) {
  // loading CAs from an InputStream
  CertificateFactory cf = CertificateFactory.getInstance("X.509");
  InputStream cert = context.getResources().openRawResource(R.raw.my_cert);
  Certificate ca;
  try {
    ca = cf.generateCertificate(cert);
  } finally { cert.close(); }

  // creating a KeyStore containing our trusted CAs
  String keyStoreType = KeyStore.getDefaultType();
  KeyStore keyStore = KeyStore.getInstance(keyStoreType);
  keyStore.load(null, null);
  keyStore.setCertificateEntry("ca", ca);

  // creating a TrustManager that trusts the CAs in our KeyStore
  String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
  TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
  tmf.init(keyStore);

  // creating an SSLSocketFactory that uses our TrustManager
  SSLContext sslContext = SSLContext.getInstance("TLS");
  sslContext.init(null, tmf.getTrustManagers(), null);

  // creating an OkHttpClient that uses our SSLSocketFactory
  OkHttpClient okHttpClient = new OkHttpClient();
  okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());

  // creating a RestAdapter that uses this custom client
  return new RestAdapter.Builder()
              .setEndpoint(UrlRepository.API_BASE)
              .setClient(new OkClient(okHttpClient))
              .build();
}

To help in debugging, I also added .setLogLevel(RestAdapter.LogLevel.FULL) to my RestAdapter creation commands and I could see it connecting and getting the response from the server.

All it took was my original .crt file saved in main/res/raw.
The .crt file, aka the certificate, is one of the two files created when you create a certificate using openssl. Generally, it is a .crt or .cert file, while the other is a .key file.

Afaik, the .crt file is your public key and the .key file is your private key.

As I can see, you already have a .cert file, which is the same, so try to use it.


PS: For those that read it in the future and only have a .pem file, according to this answer, you only need this to convert one to the other:

openssl x509 -outform der -in your-cert.pem -out your-cert.crt

PS²: For those that don’t have any file at all, you can use the following command (bash) to extract the public key (aka certificate) from any server:

echo -n | openssl s_client -connect your.server.com:443 | 
  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/my_cert.crt

Just replace the your.server.com and the port (if it is not standard HTTPS) and choose a valid path for your output file to be created.

DISCLAIMER: this answer is from Jul 2015 and uses Retrofit and OkHttp from that time.
Check this link for more info on Retrofit v2 and this one for the current OkHttp methods.

Okay, I got it working using Android Developers guide.

Just as OP, I’m trying to use Retrofit and OkHttp to connect to a self-signed SSL-enabled server.

Here’s the code that got things working (I’ve removed the try/catch blocks):

public static RestAdapter createAdapter(Context context) {
  // loading CAs from an InputStream
  CertificateFactory cf = CertificateFactory.getInstance("X.509");
  InputStream cert = context.getResources().openRawResource(R.raw.my_cert);
  Certificate ca;
  try {
    ca = cf.generateCertificate(cert);
  } finally { cert.close(); }

  // creating a KeyStore containing our trusted CAs
  String keyStoreType = KeyStore.getDefaultType();
  KeyStore keyStore = KeyStore.getInstance(keyStoreType);
  keyStore.load(null, null);
  keyStore.setCertificateEntry("ca", ca);

  // creating a TrustManager that trusts the CAs in our KeyStore
  String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
  TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
  tmf.init(keyStore);

  // creating an SSLSocketFactory that uses our TrustManager
  SSLContext sslContext = SSLContext.getInstance("TLS");
  sslContext.init(null, tmf.getTrustManagers(), null);

  // creating an OkHttpClient that uses our SSLSocketFactory
  OkHttpClient okHttpClient = new OkHttpClient();
  okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());

  // creating a RestAdapter that uses this custom client
  return new RestAdapter.Builder()
              .setEndpoint(UrlRepository.API_BASE)
              .setClient(new OkClient(okHttpClient))
              .build();
}

To help in debugging, I also added .setLogLevel(RestAdapter.LogLevel.FULL) to my RestAdapter creation commands and I could see it connecting and getting the response from the server.

All it took was my original .crt file saved in main/res/raw.
The .crt file, aka the certificate, is one of the two files created when you create a certificate using openssl. Generally, it is a .crt or .cert file, while the other is a .key file.

Afaik, the .crt file is your public key and the .key file is your private key.

As I can see, you already have a .cert file, which is the same, so try to use it.


PS: For those that read it in the future and only have a .pem file, according to this answer, you only need this to convert one to the other:

openssl x509 -outform der -in your-cert.pem -out your-cert.crt

PS²: For those that don’t have any file at all, you can use the following command (bash) to extract the public key (aka certificate) from any server:

echo -n | openssl s_client -connect your.server.com:443 | 
  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/my_cert.crt

Just replace the your.server.com and the port (if it is not standard HTTPS) and choose a valid path for your output file to be created.

Skip to content

Problem:

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

When to occur:

Connect to the server with self-signed certificate.

Solution:

There are two solutions here, one is to download the untrusted cert, and load it when connect to the server. The other one is to trust any website with any certificate which is not recommended BTW.

Solution one:

  1. Save CERT from the server, and put it to the <raw> directory:
    echo -n | openssl s_client -connect slrclub.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > <target_directory>/slrclub_cert.crt
  2. Load CERT for the OKHTTPClient:
        public static OkHttpClient getSlrClubClient(Context context) throws Exception {
            // loading CAs from an InputStream
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream cert = context.getResources().openRawResource(R.raw.slrclub_cert);
            Certificate ca;
            try {
                ca = cf.generateCertificate(cert);
            } finally { cert.close(); }
    
            // creating a KeyStore containing our trusted CAs
            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);
    
            // creating a TrustManager that trusts the CAs in our KeyStore
            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);
    
            // creating an SSLSocketFactory that uses our TrustManager
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, tmf.getTrustManagers(), null);
    
    //        okHttpClient.sslSocketFactory(sslContext.getSocketFactory());
    
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslContext.getSocketFactory());
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
    
            OkHttpClient okHttpClient = builder.build();
    
            // creating a RestAdapter using the custom client
            return okHttpClient;
        }

    AND use it when create the Retrofit:

            SlrClubService slrClubService = null;
            try {
                slrClubService = new Retrofit.Builder()
                        .baseUrl(SlrClubService.ENDPOINT)
                        .client(getUnsafeOkHttpClient())
                        .build()
                        .create(SlrClubService.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            Call<ResponseBody> slrResult = slrClubService.getMainPage();
    //        Call<ResponseBody> result = service.getMainPage();
            slrResult.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    try {
                        Log.e("ckdlee-onResponse", response.body().string());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    Log.e("ckdlee-onFailure", "Error");
                    Log.e("ckdlee", call.toString());
                    Log.e("ckdlee", t.toString());
                }
            });

Solution two:

  1. Create a unsafeOkHttpClient:
    private static OkHttpClient getUnsafeOkHttpClient() {
        try {
            // Create a trust manager that does not validate certificate chains
            final TrustManager[] trustAllCerts = new TrustManager[] {
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }
    
                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }
    
                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };
    
            // Install the all-trusting trust manager
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
    
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
    
            OkHttpClient okHttpClient = builder.build();
            return okHttpClient;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
  2. use it for Retrofit.

Ref:

  1. http://stackoverflow.com/questions/25509296/trusting-all-certificates-with-okhttp
  2. http://stackoverflow.com/questions/29273387/certpathvalidatorexception-trust-anchor-for-certificate-path-not-found-retro/31436459#31436459

Понравилась статья? Поделить с друзьями:
  • Truncated tar archive tar error exit delayed from previous errors
  • Truncate syntax error
  • Truma combi 4 коды ошибок
  • Trulaser 1030 ошибки
  • Tropico 5 как изменить язык