Disable SSL certificate verification in the modified library

I am using a modification in android to connect to the server.

public class ApiClient { public static final String BASE_URL = "https://example.com/"; private static Retrofit retrofit = null; public static Retrofit getClient() { if (retrofit==null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } } 

This is my maid. server, and I want to disable certificate verification. How can I implement in this code?

ERROR: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: The trust binding for the certification path was not found.

+6
source share
5 answers

Use this class to get an unsafe Retrofit instance. I have included imports to avoid confusion.

 import java.security.cert.CertificateException; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import okhttp3.OkHttpClient; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; import view.utils.AppConstants; /** * Created by Hitesh.Sahu on 11/23/2016. */ public class NetworkHandler { public static Retrofit getRetrofit() { return new Retrofit.Builder() .baseUrl(AppConstants.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .client(getUnsafeOkHttpClient()) .build(); } 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); } } } 

And then just use the modification without ssl as shown

  private void postFeedbackOnServer() { MyApiEndpointInterface apiService = NetworkHandler.getRetrofit().create(MyApiEndpointInterface.class); Call<ResponseBE> call = apiService.submitFeedbackToServer(requestObject); Log.e(TAG , "Request is" + new Gson().toJson(requestObject).toString() ); call.enqueue(new Callback<ResponseBE>() { @Override public void onResponse(Call<ResponseBE> call, Response<ResponseBE> response) { int statusCode = response.code(); if (statusCode == HttpURLConnection.HTTP_OK) { ...... } else { Toast.makeText(FeedbackActivity.this, "Failed to submit Data" + statusCode, Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<ResponseBE> call, Throwable t) { // Log error here since request failed Toast.makeText(FeedbackActivity.this, "Failure" + t.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); } }); } 
+16
source

I strongly recommend not doing this.

The short answer is a subclass of HostNameVerifier, over-ride verify () to always return true.

It has the best options.

Long answer - check out my (getting pretty old) blog here: Ensuring Android and SSL work together

Perhaps the best option for your scenario

Drop https to http for your test server, then the logic should not change.

NTN

+3
source

IMO, you can read the Google documentation - security using HTTPS and SSL .

About the sample code for using Retrofit with your self-signed certificate, try the following, hope this helps!

 ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try{ OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(getSSLSocketFactory()) .hostnameVerifier(getHostnameVerifier()) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL_BASE) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build(); WebAPIService service = retrofit.create(WebAPIService.class); Call<JsonObject> jsonObjectCall = service.getData(...); ... } catch (Exception e) { e.printStackTrace(); } } // for SSL... // Read more at https://developer.android.com/training/articles/security-ssl.html#CommonHostnameProbs private HostnameVerifier getHostnameVerifier() { return new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; // verify always returns true, which could cause insecure network traffic due to trusting TLS/SSL server certificates for wrong hostnames //HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); //return hv.verify("localhost", session); } }; } private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) { final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0]; return new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return originalTrustManager.getAcceptedIssuers(); } public void checkClientTrusted(X509Certificate[] certs, String authType) { try { if (certs != null && certs.length > 0){ certs[0].checkValidity(); } else { originalTrustManager.checkClientTrusted(certs, authType); } } catch (CertificateException e) { Log.w("checkClientTrusted", e.toString()); } } public void checkServerTrusted(X509Certificate[] certs, String authType) { try { if (certs != null && certs.length > 0){ certs[0].checkValidity(); } else { originalTrustManager.checkServerTrusted(certs, authType); } } catch (CertificateException e) { Log.w("checkServerTrusted", e.toString()); } } } }; } private SSLSocketFactory getSSLSocketFactory() throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException { CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caInput = getResources().openRawResource(R.raw.your_cert); // File path: app\src\main\res\raw\your_cert.cer Certificate ca = cf.generateCertificate(caInput); caInput.close(); KeyStore keyStore = KeyStore.getInstance("BKS"); keyStore.load(null, null); keyStore.setCertificateEntry("ca", ca); String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers()); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, wrappedTrustManagers, null); return sslContext.getSocketFactory(); } ... 
+3
source

Implementing such a workaround in code, even for testing purposes, is bad practice.

You can:

  • Create your CA.
  • Sign your certificate in CA.
  • Add CA as trusted.

Some links that may be helpful:

0
source
 private boolean bypassSSLVerification = true; private boolean privateCA = false; if(bypassSSLVerification) { IO.setDefaultSSLContext(SSLContextManager.getTrustAllSSLContext()); IO.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslSession) { return true; } }); } else if(privateCA) { IO.setDefaultSSLContext(SSLContextManager.getSSLContext(context)); } 

SSLContextManager.java

  public class SSLContextManager { public static SSLContext getSSLContext(Context context) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, KeyManagementException, NoSuchProviderException { // Load CAs from an InputStream CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC"); InputStream cert = context.getResources().openRawResource(R.raw.my_cert); // Place your 'my_cert.crt' file in `res/raw` Certificate ca; try { ca = cf.generateCertificate(cert); } finally { cert.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 sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), null); return sslContext; } public static SSLContext getTrustAllSSLContext() throws NoSuchAlgorithmException, KeyManagementException { // 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) { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType){ } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } } }; // Install the all-trusting trust manager SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); return sslContext; } } 
0
source

All Articles