社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
客户端httpclient访问https服务端,抛出javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
JDK1.8版本不支持服务端要求的加密算法套件,当加密密钥长度>128
由于客户端做了永久信任,服务端也要求单向认证,所以一定不是证书问题。
服务端要求TLS1.2、TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384套件
后来发现服务端指定了一个算法套件,抓包tcpdump+Wireshark发现客户端发送的client hello算法套件 不包含服务端要求的TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
服务端响应包:
Secure Sockets Layer
TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
服务端要求的是TLS1.2 ,协议版本没有问题,那就应该是加密算法套件的问题
查看本地JRE和服务端支持的加密套件,可用openssl来获取服务端
openssl s_client -connect serverxxx:443
得到一下信息,省略无关信息
SSL-Session:
Protocol : TLSv1.2
Cipher : AES256-GCM-SHA384
服务器确实需要AES256-GCM-SHA384,这是一个很长长度的强加密,一般128位长度加密就够了。
对Java代码也来一次调试,确认它所支持的所有加密套件。
-Dssl.debug=true -Djavax.net.debug=all
返回结果确实如此,根本就不存在基于AES256-GCM-SHA384的加密方法。
问题在于发行的JDK1.8版本JRE本身仅支持长度128的弱加密,它默认做了很多加密长度限制的裁剪,就是只出口强度低的加密,这是美国政府对于安全软件的强制性规定。
但Oracle允许下载强加密的未限制版本,可去官网下载一个压缩包叫做 “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 8”。对于JDK1.8版本但是低于1.8.0_151版本的JDK,将下载的包里的两个文件直接覆盖到本地 Javajrelibsecurity
local_policy.jar
US_export_policy.jar
1.8.0_151和以后的版本,只要修改Javajrelibsecurityjava.security文件,修改这一行注释并启用就可以了。
crypto.policy=unlimited
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!