Javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: Failure in SSL library, usually a protocol error

AndroidSslSslhandshakeexceptionAndroid 4.0.3-Ice-Cream-Sandwich

Android Problem Overview


I am trying to run the following code in android

URLConnection l_connection = null;
		// Create connection
		uzip=new UnZipData(mContext);
		l_url = new URL(serverurl);
		
		if ("https".equals(l_url.getProtocol())) {
			System.out.println("<<<<<<<<<<<<< Before TLS >>>>>>>>>>>>");
			sslcontext = SSLContext.getInstance("TLS");
			System.out.println("<<<<<<<<<<<<< After TLS >>>>>>>>>>>>");
			sslcontext.init(null,
					new TrustManager[] { new CustomTrustManager()},
					new java.security.SecureRandom());
			HttpsURLConnection
					.setDefaultHostnameVerifier(new CustomHostnameVerifier());
			HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext
					.getSocketFactory());
			
			l_connection = (HttpsURLConnection) l_url.openConnection();
			((HttpsURLConnection) l_connection).setRequestMethod("POST");
		} else {
			l_connection = (HttpURLConnection) l_url.openConnection();
			((HttpURLConnection) l_connection).setRequestMethod("POST");
		}
		/*System.setProperty("http.agent", "Android_Phone");*/
		
		
		l_connection.setConnectTimeout(10000);
		l_connection.setRequestProperty("Content-Language", "en-US");
		l_connection.setUseCaches(false);
		l_connection.setDoInput(true);
		l_connection.setDoOutput(true);
		System.out.println("<<<<<<<<<<<<< Before Connection >>>>>>>>>>>>");
		l_connection.connect();

On l_connection.connect() , it is giving this SSLhandshakeException. Sometimes it works, but most of the time it gives the exception. It is only happening on Android 4.0 emulator. I tested it on Android 4.4 and 5.0, it works fine. What could be the cause of this ? Please help

STACKTRACE

    04-28 15:51:13.143: W/System.err(2915): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x870c918: Failure in SSL library, usually a protocol error
04-28 15:51:13.143: W/System.err(2915): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb7c393a1:0x00000000)
04-28 15:51:13.143: W/System.err(2915): 	at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:460)
04-28 15:51:13.143: W/System.err(2915): 	at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257)
04-28 15:51:13.143: W/System.err(2915): 	at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210)
04-28 15:51:13.143: W/System.err(2915): 	at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477)
04-28 15:51:13.153: W/System.err(2915): 	at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:441)
04-28 15:51:13.153: W/System.err(2915): 	at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
04-28 15:51:13.153: W/System.err(2915): 	at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
04-28 15:51:13.153: W/System.err(2915): 	at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
04-28 15:51:13.153: W/System.err(2915): 	at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164)
04-28 15:51:13.153: W/System.err(2915): 	at com.ofss.fcdb.mobile.android.rms.helpers.NetworkConnector.getConnection(NetworkConnector.java:170)
04-28 15:51:13.153: W/System.err(2915): 	at com.ofss.fcdb.mobile.android.rms.util.InitiateRMS$2.run(InitiateRMS.java:221)
04-28 15:51:13.153: W/System.err(2915): 	at java.lang.Thread.run(Thread.java:856)
04-28 15:51:13.153: W/System.err(2915): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x870c918: Failure in SSL library, usually a protocol error
04-28 15:51:13.153: W/System.err(2915): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb7c393a1:0x00000000)
04-28 15:51:13.153: W/System.err(2915): 	at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
04-28 15:51:13.153: W/System.err(2915): 	at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410)
04-28 15:51:13.153: W/System.err(2915): 	... 11 more
04-28 16:42:44.139: W/ResourceType(3140): No package identifier when getting value for resource number 0x00000000

Android Solutions


Solution 1 - Android

I found the solution for it by analyzing the data packets using wireshark. What I found is that while making a secure connection, android was falling back to SSLv3 from TLSv1 . It is a bug in android versions < 4.4 , and it can be solved by removing the SSLv3 protocol from Enabled Protocols list. I made a custom socketFactory class called NoSSLv3SocketFactory.java. Use this to make a socketfactory.

/*Copyright 2015 Bhavit Singh Sengar
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.*/

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;


public class NoSSLv3SocketFactory extends SSLSocketFactory{
	private final SSLSocketFactory delegate;

public NoSSLv3SocketFactory() {
	this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory();
}

public NoSSLv3SocketFactory(SSLSocketFactory delegate) {
	this.delegate = delegate;
}

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

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

private Socket makeSocketSafe(Socket socket) {
	if (socket instanceof SSLSocket) {
		socket = new NoSSLv3SSLSocket((SSLSocket) socket);
	}
	return socket;
}

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

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

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

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

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

private class NoSSLv3SSLSocket extends DelegateSSLSocket {

	private NoSSLv3SSLSocket(SSLSocket delegate) {
		super(delegate);

	}

	@Override
	public void setEnabledProtocols(String[] protocols) {
		if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) {

			List<String> enabledProtocols = new ArrayList<String>(Arrays.asList(delegate.getEnabledProtocols()));
			if (enabledProtocols.size() > 1) {
				enabledProtocols.remove("SSLv3");
				System.out.println("Removed SSLv3 from enabled protocols");
			} else {
				System.out.println("SSL stuck with protocol available for " + String.valueOf(enabledProtocols));
			}
			protocols = enabledProtocols.toArray(new String[enabledProtocols.size()]);
		}

		super.setEnabledProtocols(protocols);
	}
}

public class DelegateSSLSocket extends SSLSocket {

	protected final SSLSocket delegate;

	DelegateSSLSocket(SSLSocket delegate) {
		this.delegate = delegate;
	}

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

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

	@Override
	public void setEnabledCipherSuites(String[] suites) {
		delegate.setEnabledCipherSuites(suites);
	}

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

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

	@Override
	public void setEnabledProtocols(String[] protocols) {
		delegate.setEnabledProtocols(protocols);
	}

	@Override
	public SSLSession getSession() {
		return delegate.getSession();
	}

	@Override
	public void addHandshakeCompletedListener(HandshakeCompletedListener listener) {
		delegate.addHandshakeCompletedListener(listener);
	}

	@Override
	public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) {
		delegate.removeHandshakeCompletedListener(listener);
	}

	@Override
	public void startHandshake() throws IOException {
		delegate.startHandshake();
	}

	@Override
	public void setUseClientMode(boolean mode) {
		delegate.setUseClientMode(mode);
	}

	@Override
	public boolean getUseClientMode() {
		return delegate.getUseClientMode();
	}

	@Override
	public void setNeedClientAuth(boolean need) {
		delegate.setNeedClientAuth(need);
	}

	@Override
	public void setWantClientAuth(boolean want) {
		delegate.setWantClientAuth(want);
	}

	@Override
	public boolean getNeedClientAuth() {
		return delegate.getNeedClientAuth();
	}

	@Override
	public boolean getWantClientAuth() {
		return delegate.getWantClientAuth();
	}

	@Override
	public void setEnableSessionCreation(boolean flag) {
		delegate.setEnableSessionCreation(flag);
	}

	@Override
	public boolean getEnableSessionCreation() {
		return delegate.getEnableSessionCreation();
	}

	@Override
	public void bind(SocketAddress localAddr) throws IOException {
		delegate.bind(localAddr);
	}

	@Override
	public synchronized void close() throws IOException {
		delegate.close();
	}

	@Override
	public void connect(SocketAddress remoteAddr) throws IOException {
		delegate.connect(remoteAddr);
	}

	@Override
	public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
		delegate.connect(remoteAddr, timeout);
	}

	@Override
	public SocketChannel getChannel() {
		return delegate.getChannel();
	}

	@Override
	public InetAddress getInetAddress() {
		return delegate.getInetAddress();
	}

	@Override
	public InputStream getInputStream() throws IOException {
		return delegate.getInputStream();
	}

	@Override
	public boolean getKeepAlive() throws SocketException {
		return delegate.getKeepAlive();
	}

	@Override
	public InetAddress getLocalAddress() {
		return delegate.getLocalAddress();
	}

	@Override
	public int getLocalPort() {
		return delegate.getLocalPort();
	}

	@Override
	public SocketAddress getLocalSocketAddress() {
		return delegate.getLocalSocketAddress();
	}

	@Override
	public boolean getOOBInline() throws SocketException {
		return delegate.getOOBInline();
	}

	@Override
	public OutputStream getOutputStream() throws IOException {
		return delegate.getOutputStream();
	}

	@Override
	public int getPort() {
		return delegate.getPort();
	}

	@Override
	public synchronized int getReceiveBufferSize() throws SocketException {
		return delegate.getReceiveBufferSize();
	}

	@Override
	public SocketAddress getRemoteSocketAddress() {
		return delegate.getRemoteSocketAddress();
	}

	@Override
	public boolean getReuseAddress() throws SocketException {
		return delegate.getReuseAddress();
	}

	@Override
	public synchronized int getSendBufferSize() throws SocketException {
		return delegate.getSendBufferSize();
	}

	@Override
	public int getSoLinger() throws SocketException {
		return delegate.getSoLinger();
	}

	@Override
	public synchronized int getSoTimeout() throws SocketException {
		return delegate.getSoTimeout();
	}

	@Override
	public boolean getTcpNoDelay() throws SocketException {
		return delegate.getTcpNoDelay();
	}

	@Override
	public int getTrafficClass() throws SocketException {
		return delegate.getTrafficClass();
	}

	@Override
	public boolean isBound() {
		return delegate.isBound();
	}

	@Override
	public boolean isClosed() {
		return delegate.isClosed();
	}

	@Override
	public boolean isConnected() {
		return delegate.isConnected();
	}

	@Override
	public boolean isInputShutdown() {
		return delegate.isInputShutdown();
	}

	@Override
	public boolean isOutputShutdown() {
		return delegate.isOutputShutdown();
	}

	@Override
	public void sendUrgentData(int value) throws IOException {
		delegate.sendUrgentData(value);
	}

	@Override
	public void setKeepAlive(boolean keepAlive) throws SocketException {
		delegate.setKeepAlive(keepAlive);
	}

	@Override
	public void setOOBInline(boolean oobinline) throws SocketException {
		delegate.setOOBInline(oobinline);
	}

	@Override
	public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
		delegate.setPerformancePreferences(connectionTime, latency, bandwidth);
	}

	@Override
	public synchronized void setReceiveBufferSize(int size) throws SocketException {
		delegate.setReceiveBufferSize(size);
	}

	@Override
	public void setReuseAddress(boolean reuse) throws SocketException {
		delegate.setReuseAddress(reuse);
	}

	@Override
	public synchronized void setSendBufferSize(int size) throws SocketException {
		delegate.setSendBufferSize(size);
	}

	@Override
	public void setSoLinger(boolean on, int timeout) throws SocketException {
		delegate.setSoLinger(on, timeout);
	}

	@Override
	public synchronized void setSoTimeout(int timeout) throws SocketException {
		delegate.setSoTimeout(timeout);
	}

	@Override
	public void setTcpNoDelay(boolean on) throws SocketException {
		delegate.setTcpNoDelay(on);
	}

	@Override
	public void setTrafficClass(int value) throws SocketException {
		delegate.setTrafficClass(value);
	}

	@Override
	public void shutdownInput() throws IOException {
		delegate.shutdownInput();
	}

	@Override
	public void shutdownOutput() throws IOException {
		delegate.shutdownOutput();
	}

	@Override
	public String toString() {
		return delegate.toString();
	}

	@Override
	public boolean equals(Object o) {
		return delegate.equals(o);
	}
}
}

Use this class like this while connecting :

SSLContext sslcontext = SSLContext.getInstance("TLSv1");
sslcontext.init(null, null, null);
SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory());
			
HttpsURLConnection.setDefaultSSLSocketFactory(NoSSLv3Factory);
l_connection = (HttpsURLConnection) l_url.openConnection();
l_connection.connect();

UPDATE :

Now, correct solution would be to install a newer security provider using Google Play Services:

    ProviderInstaller.installIfNeeded(getApplicationContext());

This effectively gives your app access to a newer version of OpenSSL and Java Security Provider, which includes support for TLSv1.2 in SSLEngine. Once the new provider is installed, you can create an SSLEngine which supports SSLv3, TLSv1, TLSv1.1 and TLSv1.2 the usual way:

    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(null, null, null);
    SSLEngine engine = sslContext.createSSLEngine();

Or you can restrict the enabled protocols using engine.setEnabledProtocols.

Don't forget to add the following dependency (check the latest version here):

implementation 'com.google.android.gms:play-services-auth:17.0.0'

For more info, checkout this link.

Solution 2 - Android

Scenario

I was getting SSLHandshake exceptions on devices running versions of Android earlier than Android 5.0. In my use case I also wanted to create a TrustManager to trust my client certificate.

I implemented NoSSLv3SocketFactory and NoSSLv3Factory to remove SSLv3 from my client's list of supported protocols but I could get neither of these solutions to work.

Some things I learned:

  • On devices older than Android 5.0 TLSv1.1 and TLSv1.2 protocols are not enabled by default.
  • SSLv3 protocol is not disabled by default on devices older than Android 5.0.
  • SSLv3 is not a secure protocol and it is therefore desirable to remove it from our client's list of supported protocols before a connection is made.

What worked for me

Allow Android's security Provider to update when starting your app.

The default Provider before 5.0+ does not disable SSLv3. Provided you have access to Google Play services it is relatively straightforward to patch Android's security Provider from your app.

private void updateAndroidSecurityProvider(Activity callingActivity) {
    try {
        ProviderInstaller.installIfNeeded(this);
    } catch (GooglePlayServicesRepairableException e) {
        // Thrown when Google Play Services is not installed, up-to-date, or enabled
        // Show dialog to allow users to install, update, or otherwise enable Google Play services.
        GooglePlayServicesUtil.getErrorDialog(e.getConnectionStatusCode(), callingActivity, 0);
    } catch (GooglePlayServicesNotAvailableException e) {
        Log.e("SecurityException", "Google Play Services not available.");
    }
}

If you now create your OkHttpClient or HttpURLConnection TLSv1.1 and TLSv1.2 should be available as protocols and SSLv3 should be removed. If the client/connection (or more specifically it's SSLContext) was initialised before calling ProviderInstaller.installIfNeeded(...) then it will need to be recreated.

Don't forget to add the following dependency (latest version found here):

compile 'com.google.android.gms:play-services-auth:16.0.1'

Sources:

Aside

I didn't need to explicitly set which cipher algorithms my client should use but I found a SO post recommending those considered most secure at the time of writing: https://stackoverflow.com/questions/1037590/which-cipher-suites-to-enable-for-ssl-socket/23365536#23365536

Solution 3 - Android

Also you should know that you can force TLS v1.2 for Android 4.0 devices that don't have it enabled by default:

Put this code in onCreate() of your Application file:

try {
        ProviderInstaller.installIfNeeded(getApplicationContext());
        SSLContext sslContext;
        sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(null, null, null);
        sslContext.createSSLEngine();
    } catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException
            | NoSuchAlgorithmException | KeyManagementException e) {
        e.printStackTrace();
    }

Solution 4 - Android

Previously, I've also solved this problem with custom SSLFactory implementation, but according to OkHttp docs the solution is much easier.

My final solution with needed TLS ciphers for 4.2+ devices looks like this:

public UsersApi provideUsersApi() {

	private ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
        .supportsTlsExtensions(true)
        .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0)
        .cipherSuites(
                CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
                CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
                CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
                CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
                CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
                CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
                CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
                CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
                CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
                CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
        .build();

	OkHttpClient client = new OkHttpClient.Builder()
            .connectionSpecs(Collections.singletonList(spec))
            .build();

    return new Retrofit.Builder()
            .baseUrl(USERS_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build()
            .create(UsersApi.class);
}

Note that set of supported protocols depends on configured on your server.

Solution 5 - Android

I found the solution here in this link.

You just have to place below code in your Android application class. And that is enough. Don't need to do any changes in your Retrofit settings. It saved my day.

public class MyApplication extends Application {
@Override
public void onCreate() {
    super.onCreate();
    try {
      // Google Play will install latest OpenSSL 
      ProviderInstaller.installIfNeeded(getApplicationContext());
      SSLContext sslContext;
      sslContext = SSLContext.getInstance("TLSv1.2");
      sslContext.init(null, null, null);
      sslContext.createSSLEngine();
    } catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException
        | NoSuchAlgorithmException | KeyManagementException e) {
        e.printStackTrace();
        }
    }
}

Hope this will be of help. Thank you.

Solution 6 - Android

This solved it for me:

> The Android documentation for SSLSocket says that TLS 1.1 and TLS 1.2 is supported within android starting API level 16+ (Android 4.1, Jelly Bean). But it is by default disabled but starting with API level 20+ (Android 4.4 for watch, Kitkat Watch and Android 5.0 for phone, Lollipop) they are enabled. But it is very hard to find any documentation about how to enable it for phones running 4.1 for example. To enable TLS 1.1 and 1.2 you need to create a custom SSLSocketFactory that is going to proxy all calls to a default SSLSocketFactory implementation. In addition to that do we have to override all createSocket methods and callsetEnabledProtocols on the returned SSLSocket to enable TLS 1.1 and TLS 1.2. For an example implementation just follow the link below.

android 4.1. enable tls1.1 and tls 1.2

Solution 7 - Android

When I got this error, it was because the protocols (TLS versions) and/or cipher suites supported by the server were not enabled on (and possibly not even supported by) the device. For API 16-19, TLSv1.1 and TLSv1.2 are supported but not enabled by default. Once I enabled them for these versions, I still got the error because these versions don't support any of the ciphers on our instance of AWS CloudFront.

Since it's not possible to add ciphers to Android, we had to switch our CloudFront version from TLSv1.2_2018 to TLSv1.1_2016 (which still supports TLSv1.2; it just doesn't require it), which has four of the ciphers supported by the earlier Android versions, two of which are still considered strong.

At that point, the error disappeared and the calls went through (with TLSv1.2) because there was at least one protocol and at least one cipher that the device and server shared.

Refer to the tables on this page to see which protocols and ciphers are supported by and enabled on which versions of Android.

Now was Android really trying to use SSLv3 as implied by the "sslv3 alert handshake failure" part of the error message? I doubt it; I suspect this is an old cobweb in the SSL library that hasn't been cleaned out but I can't say for sure.

In order to enable TLSv1.2 (and TLSv1.1), I was able to use a much simpler SSLSocketFactory than the ones seen elsewhere (like NoSSLv3SocketFactory). It simply makes sure that the enabled protocols include all the supported protocols and that the enabled ciphers include all the supported ciphers (the latter wasn't necessary for me but it could be for others) - see configure() at the bottom. If you'd rather enable only the latest protocols, you can replace socket.supportedProtocols with something like arrayOf("TLSv1.1", "TLSv1.2") (likewise for the ciphers):

class TLSSocketFactory : SSLSocketFactory() {

    private val socketFactory: SSLSocketFactory

    init {
        val sslContext = SSLContext.getInstance("TLS")
        sslContext.init(null, null, null)
        socketFactory = sslContext.socketFactory
    }

    override fun getDefaultCipherSuites(): Array<String> {
        return socketFactory.defaultCipherSuites
    }

    override fun getSupportedCipherSuites(): Array<String> {
        return socketFactory.supportedCipherSuites
    }

    override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket {
        return configure(socketFactory.createSocket(s, host, port, autoClose) as SSLSocket)
    }

    override fun createSocket(host: String, port: Int): Socket {
        return configure(socketFactory.createSocket(host, port) as SSLSocket)
    }

    override fun createSocket(host: InetAddress, port: Int): Socket {
        return configure(socketFactory.createSocket(host, port) as SSLSocket)
    }

    override fun createSocket(host: String, port: Int, localHost: InetAddress, localPort: Int): Socket {
        return configure(socketFactory.createSocket(host, port, localHost, localPort) as SSLSocket)
    }

    override fun createSocket(address: InetAddress, port: Int, localAddress: InetAddress, localPort: Int): Socket {
        return configure(socketFactory.createSocket(address, port, localAddress, localPort) as SSLSocket)
    }

    private fun configure(socket: SSLSocket): SSLSocket {
        socket.enabledProtocols = socket.supportedProtocols
        socket.enabledCipherSuites = socket.supportedCipherSuites
        return socket
    }
}

Solution 8 - Android

I have got this error report problem, too. My code is under below.

public static void getShop() throws Exception {
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                OkHttpClient client = new OkHttpClient();
                Request request = new Request.Builder()
                        .url("https://10.0.2.2:8010/getShopInfo/aaa")
                        .build();
                Response response = client.newCall(request).execute();
                Log.d("response", response.body().string());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }).start();
}

I have my Springboot as my backend and use Android OKHttp to get information. The critical mistake i made was that i use a .url("https://10.0.2.2:8010/getShopInfo/aaa") in code of Android. But the my backend is not allowed https request. After i use .url("http://10.0.2.2:8010/getShopInfo/aaa"), then my code went well. So, i want to say my mistake is not the version of emulator, it about the request protocol. I meet another problem after doing what i said, but it's another problem, and i attach the resolve method of the new problem .
Good Luck!GUY!

Solution 9 - Android

It was reproducible only when I use proxy on genymotion(<4.4).

Check your proxy settings in Settings-> Wireless & Networks-> WiFi->(Long Press WiredSSID)-> Modify Network

Select show advanced options: set Proxy settings to NONE.

Solution 10 - Android

I solved problem by this : NoSSLv3SocketFactory.java

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class NoSSLv3SocketFactory extends SSLSocketFactory {
	private final SSLSocketFactory delegate;

	public NoSSLv3SocketFactory() {
		this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory();
	}

	public NoSSLv3SocketFactory(SSLSocketFactory delegate) {
		this.delegate = delegate;
	}

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

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

	private Socket makeSocketSafe(Socket socket) {
		if (socket instanceof SSLSocket) {
			socket = new NoSSLv3SSLSocket((SSLSocket) socket);
		}
		return socket;
	}

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

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

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

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

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

	private class NoSSLv3SSLSocket extends DelegateSSLSocket {

		private NoSSLv3SSLSocket(SSLSocket delegate) {
			super(delegate);

		}

		@Override
		public void setEnabledProtocols(String[] protocols) {
			if (protocols != null && protocols.length == 1
					&& "SSLv3".equals(protocols[0])) {

				List<String> enabledProtocols = new ArrayList<String>(
						Arrays.asList(delegate.getEnabledProtocols()));
				if (enabledProtocols.size() > 1) {
					enabledProtocols.remove("SSLv3");
					System.out.println("Removed SSLv3 from enabled protocols");
				} else {
					System.out.println("SSL stuck with protocol available for "
							+ String.valueOf(enabledProtocols));
				}
				protocols = enabledProtocols
						.toArray(new String[enabledProtocols.size()]);
			}

//			super.setEnabledProtocols(protocols);
			super.setEnabledProtocols(new String[]{"TLSv1.2"});
		}
	}

	public class DelegateSSLSocket extends SSLSocket {

		protected final SSLSocket delegate;

		DelegateSSLSocket(SSLSocket delegate) {
			this.delegate = delegate;
		}

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

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

		@Override
		public void setEnabledCipherSuites(String[] suites) {
			delegate.setEnabledCipherSuites(suites);
		}

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

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

		@Override
		public void setEnabledProtocols(String[] protocols) {
			delegate.setEnabledProtocols(protocols);
		}

		@Override
		public SSLSession getSession() {
			return delegate.getSession();
		}

		@Override
		public void addHandshakeCompletedListener(
				HandshakeCompletedListener listener) {
			delegate.addHandshakeCompletedListener(listener);
		}

		@Override
		public void removeHandshakeCompletedListener(
				HandshakeCompletedListener listener) {
			delegate.removeHandshakeCompletedListener(listener);
		}

		@Override
		public void startHandshake() throws IOException {
			delegate.startHandshake();
		}

		@Override
		public void setUseClientMode(boolean mode) {
			delegate.setUseClientMode(mode);
		}

		@Override
		public boolean getUseClientMode() {
			return delegate.getUseClientMode();
		}

		@Override
		public void setNeedClientAuth(boolean need) {
			delegate.setNeedClientAuth(need);
		}

		@Override
		public void setWantClientAuth(boolean want) {
			delegate.setWantClientAuth(want);
		}

		@Override
		public boolean getNeedClientAuth() {
			return delegate.getNeedClientAuth();
		}

		@Override
		public boolean getWantClientAuth() {
			return delegate.getWantClientAuth();
		}

		@Override
		public void setEnableSessionCreation(boolean flag) {
			delegate.setEnableSessionCreation(flag);
		}

		@Override
		public boolean getEnableSessionCreation() {
			return delegate.getEnableSessionCreation();
		}

		@Override
		public void bind(SocketAddress localAddr) throws IOException {
			delegate.bind(localAddr);
		}

		@Override
		public synchronized void close() throws IOException {
			delegate.close();
		}

		@Override
		public void connect(SocketAddress remoteAddr) throws IOException {
			delegate.connect(remoteAddr);
		}

		@Override
		public void connect(SocketAddress remoteAddr, int timeout)
				throws IOException {
			delegate.connect(remoteAddr, timeout);
		}

		@Override
		public SocketChannel getChannel() {
			return delegate.getChannel();
		}

		@Override
		public InetAddress getInetAddress() {
			return delegate.getInetAddress();
		}

		@Override
		public InputStream getInputStream() throws IOException {
			return delegate.getInputStream();
		}

		@Override
		public boolean getKeepAlive() throws SocketException {
			return delegate.getKeepAlive();
		}

		@Override
		public InetAddress getLocalAddress() {
			return delegate.getLocalAddress();
		}

		@Override
		public int getLocalPort() {
			return delegate.getLocalPort();
		}

		@Override
		public SocketAddress getLocalSocketAddress() {
			return delegate.getLocalSocketAddress();
		}

		@Override
		public boolean getOOBInline() throws SocketException {
			return delegate.getOOBInline();
		}

		@Override
		public OutputStream getOutputStream() throws IOException {
			return delegate.getOutputStream();
		}

		@Override
		public int getPort() {
			return delegate.getPort();
		}

		@Override
		public synchronized int getReceiveBufferSize() throws SocketException {
			return delegate.getReceiveBufferSize();
		}

		@Override
		public SocketAddress getRemoteSocketAddress() {
			return delegate.getRemoteSocketAddress();
		}

		@Override
		public boolean getReuseAddress() throws SocketException {
			return delegate.getReuseAddress();
		}

		@Override
		public synchronized int getSendBufferSize() throws SocketException {
			return delegate.getSendBufferSize();
		}

		@Override
		public int getSoLinger() throws SocketException {
			return delegate.getSoLinger();
		}

		@Override
		public synchronized int getSoTimeout() throws SocketException {
			return delegate.getSoTimeout();
		}

		@Override
		public boolean getTcpNoDelay() throws SocketException {
			return delegate.getTcpNoDelay();
		}

		@Override
		public int getTrafficClass() throws SocketException {
			return delegate.getTrafficClass();
		}

		@Override
		public boolean isBound() {
			return delegate.isBound();
		}

		@Override
		public boolean isClosed() {
			return delegate.isClosed();
		}

		@Override
		public boolean isConnected() {
			return delegate.isConnected();
		}

		@Override
		public boolean isInputShutdown() {
			return delegate.isInputShutdown();
		}

		@Override
		public boolean isOutputShutdown() {
			return delegate.isOutputShutdown();
		}

		@Override
		public void sendUrgentData(int value) throws IOException {
			delegate.sendUrgentData(value);
		}

		@Override
		public void setKeepAlive(boolean keepAlive) throws SocketException {
			delegate.setKeepAlive(keepAlive);
		}

		@Override
		public void setOOBInline(boolean oobinline) throws SocketException {
			delegate.setOOBInline(oobinline);
		}

		@Override
		public void setPerformancePreferences(int connectionTime, int latency,
				int bandwidth) {
			delegate.setPerformancePreferences(connectionTime, latency,
					bandwidth);
		}

		@Override
		public synchronized void setReceiveBufferSize(int size)
				throws SocketException {
			delegate.setReceiveBufferSize(size);
		}

		@Override
		public void setReuseAddress(boolean reuse) throws SocketException {
			delegate.setReuseAddress(reuse);
		}

		@Override
		public synchronized void setSendBufferSize(int size)
				throws SocketException {
			delegate.setSendBufferSize(size);
		}

		@Override
		public void setSoLinger(boolean on, int timeout) throws SocketException {
			delegate.setSoLinger(on, timeout);
		}

		@Override
		public synchronized void setSoTimeout(int timeout)
				throws SocketException {
			delegate.setSoTimeout(timeout);
		}

		@Override
		public void setTcpNoDelay(boolean on) throws SocketException {
			delegate.setTcpNoDelay(on);
		}

		@Override
		public void setTrafficClass(int value) throws SocketException {
			delegate.setTrafficClass(value);
		}

		@Override
		public void shutdownInput() throws IOException {
			delegate.shutdownInput();
		}

		@Override
		public void shutdownOutput() throws IOException {
			delegate.shutdownOutput();
		}

		@Override
		public String toString() {
			return delegate.toString();
		}

		@Override
		public boolean equals(Object o) {
			return delegate.equals(o);
		}
	}
}

Main class :

URL url = new URL("https://www.example.com/test.png");
URLConnection l_connection = null;
SSLContext sslcontext = SSLContext.getInstance("TLSv1.2");
sslcontext.init(null, null, null);
SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory());

Solution 11 - Android

My Answer is close to the above answers but you need to write the class exactly without changing anything.

public class TLSSocketFactory extends SSLSocketFactory {

private SSLSocketFactory delegate;

public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, null, null);
    delegate = context.getSocketFactory();
}

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

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

@Override
public Socket createSocket() throws IOException {
    return enableTLSOnSocket(delegate.createSocket());
}

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

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

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

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

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

private Socket enableTLSOnSocket(Socket socket) {
    if(socket != null && (socket instanceof SSLSocket)) {
        ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
    }
    return socket;
}

}

and to use it with HttpsURLConnection

HttpsURLConnection  conn = (HttpsURLConnection) url.openConnection();

int sdk = android.os.Build.VERSION.SDK_INT;
			if (sdk < Build.VERSION_CODES.LOLLIPOP) {
				if (url.toString().startsWith("https")) {
					try {
						TLSSocketFactory sc = new TLSSocketFactory();
						conn.setSSLSocketFactory(sc);
					} catch (Exception e) {
						String sss = e.toString();
					}
				}
			}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBhavit S. SengarView Question on Stackoverflow
Solution 1 - AndroidBhavit S. SengarView Answer on Stackoverflow
Solution 2 - AndroidMaurice GavinView Answer on Stackoverflow
Solution 3 - AndroidMayur GangurdeView Answer on Stackoverflow
Solution 4 - AndroidFragmentView Answer on Stackoverflow
Solution 5 - AndroidTazView Answer on Stackoverflow
Solution 6 - AndroidlittlenonameView Answer on Stackoverflow
Solution 7 - AndroidGumby The GreenView Answer on Stackoverflow
Solution 8 - AndroidX.ProfessorView Answer on Stackoverflow
Solution 9 - AndroidyifanView Answer on Stackoverflow
Solution 10 - AndroidGirish PatelView Answer on Stackoverflow
Solution 11 - AndroidWowo OtView Answer on Stackoverflow