Javax.net.ssl.SSLHandshakeException:javax.net.ssl.SSLProtocolException:SSL 握手中止:SSL 库失败,通常是协议错误 [英] Javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: Failure in SSL library, usually a protocol error

查看:126
本文介绍了Javax.net.ssl.SSLHandshakeException:javax.net.ssl.SSLProtocolException:SSL 握手中止:SSL 库失败,通常是协议错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 android 中运行以下代码

URLConnection l_connection = null;//创建连接uzip=新的解压缩数据(mContext);l_url = 新 URL(serverurl);if ("https".equals(l_url.getProtocol())) {System.out.println("<<<<<<<<<<<<在TLS之前>>>>>>;>>>>");sslcontext = SSLContext.getInstance("TLS");System.out.println("<<<<<<<<<<<在TLS之后>>>>>>;>>>>");sslcontext.init(空,new TrustManager[] { new CustomTrustManager()},新的 java.security.SecureRandom());HttpsURL连接.setDefaultHostnameVerifier(new CustomHostnameVerifier());HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());l_connection = (HttpsURLConnection) l_url.openConnection();((HttpsURLConnection) l_connection).setRequestMethod("POST");} 别的 {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("<<<<<<<<<<<<连接前>>>>>>;>>>>");l_connection.connect();

l_connection.connect() 上,它给出了这个 SSLhandshakeException.有时它有效,但大多数时候它会给出例外.它只发生在 Android 4.0 模拟器上.我在 Android 4.4 和 5.0 上对其进行了测试,效果很好.这可能是什么原因?请帮忙

堆栈跟踪

 04-28 15:51:13.143:W/System.err(2915):javax.net.ssl.SSLHandshakeException:javax.net.ssl.SSLProtocolException:SSL 握手中止:ssl=0x870c918:失败SSL 库,通常是协议错误04-28 15:51:13.143: W/System.err(2915): 错误:14077410:SSL 例程:SSL23_GET_SERVER_HELLO:sslv3 警报握手失败 (external/openssl/ssl/s23_clnt.c:67030030x00x0700300x00b)04-28 15:51:13.143:W/System.err(2915):在 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:460)04-28 15:51:13.143:W/System.err(2915):在 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257)04-28 15:51:13.143:W/System.err(2915):在 libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210)04-28 15:51:13.143:W/System.err(2915):在 libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477)04-28 15:51:13.153:W/System.err(2915):在 libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:441)04-28 15:51:13.153:W/System.err(2915):在 libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)04-28 15:51:13.153:W/System.err(2915):在 libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)04-28 15:51:13.153:W/System.err(2915):在 libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)04-28 15:51:13.153:W/System.err(2915):在 libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164)04-28 15:51:13.153:W/System.err(2915):在 com.ofss.fcdb.mobile.android.rms.helpers.NetworkConnector.getConnection(NetworkConnector.java:170)04-28 15:51:13.153:W/System.err(2915):在 com.ofss.fcdb.mobile.android.rms.util.InitiateRMS$2.run(InitiateRMS.java:221)04-28 15:51:13.153: W/System.err(2915): 在 java.lang.Thread.run(Thread.java:856)04-28 15:51:13.153:W/System.err(2915):引起:javax.net.ssl.SSLProtocolException:SSL 握手中止:ssl=0x870c918:SSL 库失败,通常是协议错误04-28 15:51:13.153: W/System.err(2915): 错误:14077410:SSL 例程:SSL23_GET_SERVER_HELLO:sslv3 警报握手失败 (external/openssl/ssl/s23_clnt.c:67030030x00x070000x00x0304-28 15:51:13.153:W/System.err(2915):在 org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(本地方法)04-28 15:51:13.153:W/System.err(2915):在 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410)04-28 15:51:13.153:W/System.err(2915):……还有 11 个04-28 16:42:44.139:W/ResourceType(3140):获取资源编号 0x00000000 的值时没有包标识符

解决方案

我通过使用 wireshark 分析数据包找到了解决方案.我发现在建立安全连接时,android 正在从 TLSv1 回退到 SSLv3 .这是 android 版本中的一个错误 <4.4 ,可以通过从启用的协议列表中删除 SSLv3 协议来解决.我创建了一个名为 NoSSLv3SocketFactory.java 的自定义 socketFactory 类.用它来制作一个socketfactory.

/*Copyright 2015 Bhavit Singh Sengar根据 Apache 许可,版本 2.0(许可")获得许可;除非符合许可证,否则您不得使用此文件.您可以在以下位置获得许可证的副本http://www.apache.org/licenses/LICENSE-2.0除非适用法律要求或书面同意,否则软件根据许可证分发的分发是按原样"分发的,不作任何形式的明示或暗示的保证或条件.请参阅许可证以了解管理权限的特定语言和许可证下的限制.*/导入 java.io.IOException;导入 java.io.InputStream;导入 java.io.OutputStream;导入 java.net.InetAddress;导入 java.net.Socket;导入 java.net.SocketAddress;导入 java.net.SocketException;导入 java.nio.channels.SocketChannel;导入 java.util.ArrayList;导入 java.util.Arrays;导入 java.util.List;导入 javax.net.ssl.HandshakeCompletedListener;导入 javax.net.ssl.HttpsURLConnection;导入 javax.net.ssl.SSLSession;导入 javax.net.ssl.SSLSocket;导入 javax.net.ssl.SSLSocketFactory;公共类 NoSSLv3SocketFactory 扩展了 SSLSocketFactory{私有的最终 SSLSocketFactory 委托;公共 NoSSLv3SocketFactory() {this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory();}公共 NoSSLv3SocketFactory(SSLSocketFactory 委托){this.delegate = 委托;}@覆盖公共字符串[] getDefaultCipherSuites() {返回delegate.getDefaultCipherSuites();}@覆盖公共字符串[] getSupportedCipherSuites() {返回 delegate.getSupportedCipherSuites();}私有套接字 makeSocketSafe(套接字套接字){如果(SSLSocket 的套接字实例){socket = new NoSSLv3SSLSocket((SSLSocket) socket);}返回套接字;}@覆盖public Socket createSocket(Socket s, String host, int port, boolean autoClose) 抛出 IOException {return makeSocketSafe(delegate.createSocket(s, host, port, autoClose));}@覆盖公共套接字 createSocket(String host, int port) 抛出 IOException {return makeSocketSafe(delegate.createSocket(host, port));}@覆盖public Socket createSocket(String host, int port, InetAddress localHost, int localPort) 抛出 IOException {return makeSocketSafe(delegate.createSocket(host, port, localHost, localPort));}@覆盖公共套接字 createSocket(InetAddress host, int port) 抛出 IOException {return makeSocketSafe(delegate.createSocket(host, port));}@覆盖public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) 抛出 IOException {return makeSocketSafe(delegate.createSocket(address, port, localAddress, localPort));}私有类 NoSSLv3SSLSocket 扩展了 DelegateSSLSocket {私有 NoSSLv3SSLSocket(SSLSocket 委托){超级(委托);}@覆盖public void setEnabledProtocols(String[] 协议) {if (protocols != null &&protocols.length == 1 && "SSLv3".equals(protocols[0])) {列表<字符串>enabledProtocols = new ArrayList(Arrays.asList(delegate.getEnabledProtocols()));如果(已启用的Protocols.size()> 1){enabledProtocols.remove("SSLv3");System.out.println("从启用的协议中删除了 SSLv3");} 别的 {System.out.println("SSL 卡在可用的协议上" + String.valueOf(enabledProtocols));}协议 = enabledProtocols.toArray(new String[enabledProtocols.size()]);}super.setEnabledProtocols(协议);}}公共类 DelegateSSLSocket 扩展 SSLSocket {受保护的最终 SSLSocket 委托;委托SSLSocket(SSLSocket委托){this.delegate = 委托;}@覆盖公共字符串[] getSupportedCipherSuites() {返回 delegate.getSupportedCipherSuites();}@覆盖公共字符串[] getEnabledCipherSuites() {返回 delegate.getEnabledCipherSuites();}@覆盖公共无效setEnabledCipherSuites(字符串[]套件){delegate.setEnabledCipherSuites(suites);}@覆盖公共字符串[] getSupportedProtocols() {返回委托.getSupportedProtocols();}@覆盖公共字符串[] getEnabledProtocols() {返回委托.getEnabledProtocols();}@覆盖public void setEnabledProtocols(String[] 协议) {委托.setEnabledProtocols(协议);}@覆盖公共 SSLSession getSession() {返回委托.getSession();}@覆盖公共无效 addHandshakeCompletedListener(HandshakeCompletedListener 监听器) {delegate.addHandshakeCompletedListener(listener);}@覆盖公共无效 removeHandshakeCompletedListener(HandshakeCompletedListener 监听器){delegate.removeHandshakeCompletedListener(listener);}@覆盖public void startHandshake() 抛出 IOException {委托.startHandshake();}@覆盖公共无效setUseClientMode(布尔模式){delegate.setUseClientMode(mode);}@覆盖公共布尔 getUseClientMode() {返回委托.getUseClientMode();}@覆盖public void setNeedClientAuth(boolean need) {delegate.setNeedClientAuth(need);}@覆盖public void setWantClientAuth(boolean want) {委托.setWantClientAuth(想要);}@覆盖公共布尔 getNeedClientAuth() {返回委托.getNeedClientAuth();}@覆盖公共布尔 getWantClientAuth() {返回委托.getWantClientAuth();}@覆盖公共无效setEnableSessionCreation(布尔标志){delegate.setEnableSessionCreation(flag);}@覆盖公共布尔 getEnableSessionCreation() {返回委托.getEnableSessionCreation();}@覆盖public void bind(SocketAddress localAddr) 抛出 IOException {委托.绑定(本地地址);}@覆盖公共同步 void close() 抛出 IOException {委托.关闭();}@覆盖public void connect(SocketAddress remoteAddr) 抛出 IOException {委托.connect(remoteAddr);}@覆盖public void connect(SocketAddress remoteAddr, int timeout) 抛出 IOException {委托.connect(remoteAddr, timeout);}@覆盖公共 SocketChannel getChannel() {返回委托.getChannel();}@覆盖公共 InetAddress getInetAddress() {返回委托.getInetAddress();}@覆盖public InputStream getInputStream() 抛出 IOException {返回委托.getInputStream();}@覆盖public boolean getKeepAlive() 抛出 SocketException {返回委托.getKeepAlive();}@覆盖公共 InetAddress getLocalAddress() {返回委托.getLocalAddress();}@覆盖公共 int getLocalPort() {返回委托.getLocalPort();}@覆盖公共 SocketAddress getLocalSocketAddress() {返回委托.getLocalSocketAddress();}@覆盖public boolean getOOBInline() 抛出 SocketException {返回委托.getOOBInline();}@覆盖公共输出流 getOutputStream() 抛出 IOException {返回委托.getOutputStream();}@覆盖公共 int getPort() {返回委托.getPort();}@覆盖公共同步 int getReceiveBufferSize() 抛出 SocketException {返回委托.getReceiveBufferSize();}@覆盖公共 SocketAddress getRemoteSocketAddress() {返回delegate.getRemoteSocketAddress();}@覆盖public boolean getReuseAddress() 抛出 SocketException {返回委托.getReuseAddress();}@覆盖公共同步 int getSendBufferSize() 抛出 SocketException {返回委托.getSendBufferSize();}@覆盖public int getSoLinger() 抛出 SocketException {返回委托.getSoLinger();}@覆盖公共同步 int getSoTimeout() 抛出 SocketException {返回委托.getSoTimeout();}@覆盖public boolean getTcpNoDelay() 抛出 SocketException {返回委托.getTcpNoDelay();}@覆盖public int getTrafficClass() 抛出 SocketException {返回委托.getTrafficClass();}@覆盖公共布尔 isBound() {返回委托.isBound();}@覆盖公共布尔 isClosed() {返回委托.isClosed();}@覆盖公共布尔 isConnected() {返回委托.isConnected();}@覆盖公共布尔 isInputShutdown() {返回委托.isInputShutdown();}@覆盖公共布尔 isOutputShutdown() {返回委托.isOutputShutdown();}@覆盖public void sendUrgentData(int value) 抛出 IOException {委托.sendUrgentData(value);}@覆盖public void setKeepAlive(boolean keepAlive) 抛出 SocketException {委托.setKeepAlive(keepAlive);}@覆盖public void setOOBInline(boolean oobinline) 抛出 SocketException {委托.setOOBInline(oobinline);}@覆盖public void setPerformancePreferences(int connectionTime,int延迟,int带宽){delegate.setPerformancePreferences(连接时间,延迟,带宽);}@覆盖公共同步无效 setReceiveBufferSize(int size) 抛出 SocketException {delegate.setReceiveBufferSize(size);}@覆盖公共无效 setReuseAddress(布尔重用)抛出 SocketException {委托.setReuseAddress(重用);}@覆盖公共同步无效 setSendBufferSize(int size) 抛出 SocketException {delegate.setSendBufferSize(size);}@覆盖public void setSoLinger(boolean on, int timeout) 抛出 SocketException {delegate.setSoLinger(on, timeout);}@覆盖公共同步无效 setSoTimeout(int timeout) 抛出 SocketException {委托.setSoTimeout(超时);}@覆盖public void setTcpNoDelay(boolean on) 抛出 SocketException {委托.setTcpNoDelay(on);}@覆盖public void setTrafficClass(int value) 抛出 SocketException {delegate.setTrafficClass(value);}@覆盖public void shutdownInput() 抛出 IOException {委托.shutdownInput();}@覆盖public void shutdownOutput() 抛出 IOException {委托.shutdownOutput();}@覆盖公共字符串 toString() {返回委托.toString();}@覆盖公共布尔等于(对象 o){返回delegate.equals(o);}}}

在连接时像这样使用这个类:

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();

更新:

现在,正确的解决方案是使用 Google Play 服务:

 ProviderInstaller.installIfNeeded(getApplicationContext());

这有效地使您的应用能够访问更新版本的 OpenSSL 和 Java 安全提供程序,其中包括对 SSLEngine 中的 TLSv1.2 的支持.安装新提供程序后,您可以按照通常的方式创建支持 SSLv3、TLSv1、TLSv1.1 和 TLSv1.2 的 SSLEngine:

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

或者您可以使用 engine.setEnabledProtocols 限制启用的协议.

不要忘记添加以下依赖项(在此处查看最新版本):

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

有关详细信息,请查看此链接.>

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

解决方案

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.

这篇关于Javax.net.ssl.SSLHandshakeException:javax.net.ssl.SSLProtocolException:SSL 握手中止:SSL 库失败,通常是协议错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆