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
问题描述
我正在尝试在 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屋!