您的位置:首页 > 大数据 > 人工智能

Android 6.0 HTTPS SSL 无法访问,提示Handshake failed(握手失败),解决方案

2016-08-31 09:07 681 查看

前言

之前开发的一个项目使用的是http请求,但是安全公司给出了一个安全报告,建议使用https协议来访问网络资源,使用私签证书来实现了https。Android 6.0以下的版本均可以使用,Android 6.0及以上的机型请求成功,并且在logcat中有Handshake failed的Exception。

分析

Android 6.0以下可以访问,6.0及以上不可以,初步判断是因为Android版本更新造成的,

经过一番google之,根据本地报错含有BAD_DH_P_LENGTH关键字。

确定问题出现在Java ssl 加密漏洞上。

在握手过程中,必定会涉及到公钥加密,私钥解密的过程,而该过程中,当服务端选择使用诸如TLS_DHE_RSA_WITH_AES_128_CBC_SHA等算法进行加密时,需要使用到Diffie-Hellman算法进行加密解密,通过阅读Diffie-Hellman算法的介绍,发现在加密解密计算过程中,会使用到两个参数,一个是q,一个是a,而在JDK8之前,服务器端提供的q参数只是用了768bit的长度,而不足1024bit则存在相应的安全漏洞,会被替换后的BroingSSL拒绝,因此出现了Handshake failed错误。

文/一只猿_(简书作者)

原文链接:http://www.jianshu.com/p/40c17846e626

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

解决方案

方案一、修改tomcat

配置Tomcat服务器,限制加密方式:

修改Tomcat服务器conf/server.xml文件中和Https有关的Connector节点,添加ciphers用于指定密钥:

SSLEnabled=”true”

clientAuth=”false”

connectionTimeout=”20000”

keystoreFile=”/usr/xinwei/tienlen/apache-tomcat-https/server.keystore”

keystorePass=”xinwei”

maxThreads=”150”

port=”443”

protocol=”org.apache.coyote.http11.Http11Protocol”

redirectPort=”8443”

scheme=”https”

secure=”true”

ciphers=”TLS_RSA_WITH_AES_128_CBC_SHA256,

TLS_RSA_WITH_AES_128_CBC_SHA,

TLS_RSA_WITH_AES_256_CBC_SHA256,

TLS_RSA_WITH_AES_256_CBC_SHA,

SSL_RSA_WITH_3DES_EDE_CBC_SHA”

sslProtocol=”TLS”

truststoreFile=”/usr/xinwei/tienlen/apache-tomcat-https/server.keystore”

truststorePass=”密码”

/>

添加完该配置后,重启,测试,Android6.0版本没有再发现Handshake failed错误。

文/一只猿_(简书作者)

原文链接:http://www.jianshu.com/p/40c17846e626

著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

很遗憾,我们服务器使用的是JDK 1.6、tomcat 7 ,配置ciphers,启动服务后会报错,报错原因是不识别加密方式、所以我们没有采用这个方式,应该是因为TSL协议的版本问题

方案二、升级JDK至1.8版本

我们采用这个方式,成功修复了SSL Handshake failed的问题,只要代码中没有使用Java8 不再兼容的特性,一般没有问题。

方案三、使用OKhttp时客户端修改SSL配置客户端加密套件(未验证,收录)

OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.addNetworkInterceptor(new StethoInterceptor())
.followSslRedirects(true)
.connectionSpecs(Collections.singletonList(getConnectionSpec()))
.build();

private static ConnectionSpec getConnectionSpec() {
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS).tlsVersions(TlsVersion.TLS_1_0).cipherSuites(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256, CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA).build();
return spec;
}


https三次握手:

客户端发送 TLS版本号 加密套件(这里) 随机数 hello

服务端根据客户端发送的加密套件、TLS版本号 选择对应的加密协议及套件 把加密协议、加密套件、随机数、服务端证书、hello发送给客户端

客户端收到信息后 生成随机数(通过公钥进行加密) 编码结速通知 握手结束通知

服务端 通过私钥解密 编码改变通知 握手结束通知

对称加密数据传输
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐