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

后端 未结 11 693
终归单人心
终归单人心 2020-11-22 10:55

I am trying to run the following code in android

URLConnection l_connection = null;
        // Create connection
        uzip=new UnZipData(mContext);
               


        
相关标签:
11条回答
  • 2020-11-22 11:51

    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());
    
    0 讨论(0)
  • 2020-11-22 11:56

    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

    0 讨论(0)
  • 2020-11-22 11:58

    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.

    0 讨论(0)
  • 2020-11-22 11:58

    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:

    • Patching the Security Provider with ProviderInstaller Provider
    • Making SSLEngine use TLSv1.2 on Android (4.4.2)

    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: Which Cipher Suites to enable for SSL Socket?

    0 讨论(0)
  • 2020-11-22 11:59

    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.

    0 讨论(0)
提交回复
热议问题