对您的问题的简短回答,即特别信任所有证书,是使用 TrustAllStrategy 并执行以下操作:
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
sslContextBuilder.loadTrustMaterial(null, new TrustAllStrategy());
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
sslContextBuilder.build());
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(
socketFactory).build();
但是...无效的证书可能不是您的主要问题。发生握手失败的原因有很多,但根据我的经验,这通常是由于 SSL/TLS 版本不匹配或密码套件协商失败。这并不意味着 ssl 证书是“坏的”,它只是服务器和客户端之间的不匹配。您可以使用 Wireshark (more on that) 等工具准确查看握手失败的位置
虽然 Wireshark 可以很好地了解它的失败之处,但它并不能帮助您找到解决方案。每当我过去调试 handshake_failures 时,我发现这个工具特别有用:https://testssl.sh/
您可以将该脚本指向任何失败的网站,以详细了解该目标上可用的协议以及您的客户端需要支持什么才能建立成功的握手。它还将打印有关证书的信息。
例如(仅显示 testssl.sh 输出的两个部分):
./testssl.sh www.google.com
....
Testing protocols (via sockets except TLS 1.2, SPDY+HTTP2)
SSLv2 not offered (OK)
SSLv3 not offered (OK)
TLS 1 offered
TLS 1.1 offered
TLS 1.2 offered (OK)
....
Server Certificate #1
Signature Algorithm SHA256 with RSA
Server key size RSA 2048 bits
Common Name (CN) "www.google.com"
subjectAltName (SAN) "www.google.com"
Issuer "Google Internet Authority G3" ("Google Trust Services" from "US")
Trust (hostname) Ok via SAN and CN (works w/o SNI)
Chain of trust "/etc/*.pem" cannot be found / not readable
Certificate Expiration expires < 60 days (58) (2018-10-30 06:14 --> 2019-01-22 06:14 -0700)
....
Testing all 102 locally available ciphers against the server, ordered by encryption strength
(Your /usr/bin/openssl cannot show DH/ECDH bits)
Hexcode Cipher Suite Name (OpenSSL) KeyExch. Encryption Bits
------------------------------------------------------------------------
xc030 ECDHE-RSA-AES256-GCM-SHA384 ECDH AESGCM 256
xc02c ECDHE-ECDSA-AES256-GCM-SHA384 ECDH AESGCM 256
xc014 ECDHE-RSA-AES256-SHA ECDH AES 256
xc00a ECDHE-ECDSA-AES256-SHA ECDH AES 256
x9d AES256-GCM-SHA384 RSA AESGCM 256
x35 AES256-SHA RSA AES 256
xc02f ECDHE-RSA-AES128-GCM-SHA256 ECDH AESGCM 128
xc02b ECDHE-ECDSA-AES128-GCM-SHA256 ECDH AESGCM 128
xc013 ECDHE-RSA-AES128-SHA ECDH AES 128
xc009 ECDHE-ECDSA-AES128-SHA ECDH AES 128
x9c AES128-GCM-SHA256 RSA AESGCM 128
x2f AES128-SHA RSA AES 128
x0a DES-CBC3-SHA RSA 3DES 168
因此,使用此输出我们可以看到,如果您的客户端仅支持 SSLv3,则握手将失败,因为服务器不支持该协议。提供的协议不太可能是问题,但您可以通过获取启用的协议列表来仔细检查您的 java 客户端支持的内容。您可以从上面的代码 sn-p 提供 SSLConnectionSocketFactory 的重写实现,以获取启用/支持的协议和密码套件列表,如下所示 (SSLSocket):
class MySSLConnectionSocketFactory extends SSLConnectionSocketFactory {
@Override
protected void prepareSocket(SSLSocket socket) throws IOException {
System.out.println("Supported Ciphers" + Arrays.toString(socket.getSupportedCipherSuites()));
System.out.println("Supported Protocols" + Arrays.toString(socket.getSupportedProtocols()));
System.out.println("Enabled Ciphers" + Arrays.toString(socket.getEnabledCipherSuites()));
System.out.println("Enabled Protocols" + Arrays.toString(socket.getEnabledProtocols()));
}
}
当密码套件协商失败时,我经常遇到handshake_failure。为避免此错误,您的客户端支持的密码套件列表必须至少包含与服务器支持的密码套件列表中的密码套件匹配的一个。
如果服务器需要基于 AES256 的密码套件,您可能需要 java 加密扩展 (JCE)。这些图书馆受国家限制,因此美国以外的人可能无法使用它们。
更多关于密码学限制的信息,如果您有兴趣:https://crypto.stackexchange.com/questions/20524/why-there-are-limitations-on-using-encryption-with-keys-beyond-certain-length