5

I'm creating authorization app, where I'm using Retrofit 2. When I'm doing call, that goes to onFailure method and gets exception

"javax.net.ssl.SSLException: Connection closed by peer"

But the problem is, that yesterday this worked great. Today it gives exception. I find in internet some SSLException - Connection closed by peer on Android 4.x versions, or this How to add TLS v 1.0 and TLS v.1.1 with Retrofit, but this not helped me. Any ideas how to fix it. In backend TLS1.2 is enable.

public class RegistrationFragment extends BaseFragment {
View mainView;

ApiClient apiClient = ApiClient.getInstance();

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mainView = inflater.inflate
            (R.layout.registration_fragment, container, false);

            //Calling the authorization method
            registerCall();
        }
    });

    return mainView;
}

//User authorization method

public void registerCall() {

    Call<ResponseBody> call = apiClient.registration(supportopObj);
    call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if (response.isSuccessful()) {

                //Calling the clientCall method for getting the user clientID and clientSecret
                Toast.makeText(getActivity(), "Registration Successful ",
                        Toast.LENGTH_SHORT).show();;

            } else {
                //if the response not successful
                Toast.makeText(getActivity(), "Could not register the user maybe already registered ",
                        Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Toast.makeText(getActivity(), "An error occurred", Toast.LENGTH_SHORT).show();
        }
    });
}
}
Henrik Aasted Sørensen
  • 6,966
  • 11
  • 51
  • 60
Hayk Mkrtchyan
  • 2,835
  • 3
  • 19
  • 61

2 Answers2

0

It is not because of Retrofit but instead because of okhttp. If you use okhttp version 3.x , you will come across this issue. The immediate solution would be to use okhttp version 2.x. One more thing to add is that this issue only occurs for Android versions 16-20 Link for reference

Yogesh Telang
  • 74
  • 1
  • 6
0

I used something like this in my OkHttp initialize class, but is it safe to use here?

I'm created a new class Tls12SocketFactory.class

Here is it.

public class Tls12SocketFactory extends SSLSocketFactory {
private static final String[] TLS_V12_ONLY = {"TLSv1.2"};

final SSLSocketFactory delegate;

public Tls12SocketFactory(SSLSocketFactory base) {
    this.delegate = base;
}

@Override
public String[] getDefaultCipherSuites() {
    return delegate.getDefaultCipherSuites();
}

@Override
public String[] getSupportedCipherSuites() {
    return delegate.getSupportedCipherSuites();
}

@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
    return patch(delegate.createSocket(s, host, port, autoClose));
}

@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
    return patch(delegate.createSocket(host, port));
}

@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
    return patch(delegate.createSocket(host, port, localHost, localPort));
}

@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
    return patch(delegate.createSocket(host, port));
}

@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
    return patch(delegate.createSocket(address, port, localAddress, localPort));
}

private Socket patch(Socket s) {
    if (s instanceof SSLSocket) {
        ((SSLSocket) s).setEnabledProtocols(TLS_V12_ONLY);
    }
    return s;
}
}

And I done something like this in OkHttp initialize class.

X509TrustManager trustManager = null;

    try {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init((KeyStore) null);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
            throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
        }
         trustManager = (X509TrustManager) trustManagers[0];
    } catch (KeyStoreException | NoSuchAlgorithmException e) {
        e.printStackTrace();
    }

    OkHttpClient.Builder client = new OkHttpClient.Builder()
            .readTimeout(10, TimeUnit.SECONDS)
            .connectTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS);

    try {
        SSLContext sc = SSLContext.getInstance("TLSv1.2");
        sc.init(null, new TrustManager[] { trustManager }, null);
        client.sslSocketFactory(new Tls12SocketFactory(sc.getSocketFactory()), trustManager);
        ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
                .tlsVersions(TlsVersion.TLS_1_2)
                .build();
        client.connectionSpecs(Collections.singletonList(cs));
    } catch (NoSuchAlgorithmException | KeyManagementException e) {
        e.printStackTrace();
    }

 name = new Retrofit.Builder()
            .baseUrl(endpoint)
            .client(client.build())
            .addConverterFactory(GsonConverterFactory.create())
            .build();

So is it safe to use this code in Android studio. And шill there be any problems in the future from this code? Thank you. I think my answer can help anyone else too.

Hayk Mkrtchyan
  • 2,835
  • 3
  • 19
  • 61