java - SSLHandshakeException:握手失败 SSL 例程:OPENSSL_internal:WRONG_VERSION_NUMBER
问题描述
一段时间后回到Android。我刚刚购买了一个 EV 证书并尝试使用 SSL/TSL 连接到我的 Web 服务。我越来越:
2021-07-23 09:52:12.009 26190-26225/xx.xx.wb5000dispenser E/xx.xx.wb5000dispenser.service.DispenseServiceImpl: Error registering site
javax.net.ssl.SSLHandshakeException: Handshake failed
at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:286)
at com.android.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:192)
at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:149)
at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:112)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:184)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:299)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:237)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:472)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:258)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:26)
at xx.xx.wb5000dispenser.service.DispenseServiceImpl.callPost(DispenseServiceImpl.java:72)
at xx.xx.wb5000dispenser.service.DispenseServiceImpl.registerSite(DispenseServiceImpl.java:50)
at xx.xx.wb5000dispenser.service.Wb5000Service$DailyRegisterThread.run(Wb5000Service.java:57)
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x9fa470c8: Failure in SSL library, usually a protocol error
error:100000f7:SSL routines:OPENSSL_internal:WRONG_VERSION_NUMBER (external/boringssl/src/ssl/tls_record.cc:242 0x9d1e6f1b:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.NativeSsl.doHandshake(NativeSsl.java:375)
at com.android.org.conscrypt.ConscryptFileDescriptorSocket.startHandshake(ConscryptFileDescriptorSocket.java:224)
... 16 more
我在这里的一个答案中发现我应该尝试testssl.sh。我安装了它,这是一些报告......
...
Testing protocols via sockets except NPN+ALPN
SSLv2 not offered (OK)
SSLv3 not offered (OK)
TLS 1 not offered
TLS 1.1 not offered
TLS 1.2 offered (OK)
TLS 1.3 offered (OK): final
NPN/SPDY http/1.1 (advertised)
ALPN/HTTP2 http/1.1 (offered)
...
Rating (experimental)
Rating specs (not complete) SSL Labs's 'SSL Server Rating Guide' (version 2009q from 2020-01-30)
Specification documentation https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide
Protocol Support (weighted) 100 (30)
Key Exchange (weighted) 90 (27)
Cipher Strength (weighted) 90 (36)
Final Score 93
Overall Grade A
Grade cap reasons Grade capped to A. HSTS is not offered
让我知道看更多内容是否有用...
我查看了服务器(托管在 AWS 上的 nginx),在此期间日志中没有错误。
这是 SSL 上下文的创建:
try {
sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, new java.security.SecureRandom());
} catch (NoSuchAlgorithmException | KeyManagementException ex) {
Log.e(TAG, "Error creating SSL context", ex);
}
TSLv1.3 因不受支持而失败。
这是我的连接代码:
try {
URL url = new URL(urlName);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
urlConnection.setDoOutput(true);
urlConnection.setFixedLengthStreamingMode(bytesToSend.length);
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream()); //Exception here
out.write(bytesToSend);
out.flush();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
result = readStreamAsString(in);
}
catch(Exception exception) {
Log.e(TAG, "Error registering site", exception);
throw new Square1Exception("Error hitting:" + urlName, exception);
}
如创建输出流时指示的那样爆炸。
我的平板电脑运行的是 Android 9,它比我发现的大多数类似问题都要新。
所有建议表示赞赏。
解决方案
正如 Joy 和 alexrait 所建议的,问题在于没有指定 SSL 上下文。显然,默认情况下,android 不会尝试最好的。:(
所以,我在这里添加了代码:
try {
sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, null, new java.security.SecureRandom());
} catch (NoSuchAlgorithmException | KeyManagementException ex) {
Log.e(TAG, "Error creating SSL context", ex);
}
然后添加这一行来使用它:
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
现在一切似乎都在正常工作。谢谢您的帮助。
推荐阅读
- haskell - 列出从 Haskell 到 SML 的 colgebra 转换代码
- node.js - OpenAPI java生成的客户端类未找到错误
- reactjs - 私有 S3 + CloudFront 反应应用程序:“XML 文件似乎没有任何与之关联的样式信息”
- c# - 如何从 C# windows 窗体调用 Powershell 脚本并传递参数
- python - 如何在每次出现给定字符串时拆分 Python 数组?
- sql - SQL 按 CASE WHEN 聚合记录
- java - 如何修复我的 java 程序不停止运行?
- r - 如何为列中的重复值生成增加数字的后缀?
- python - K 均值聚类:更新每个聚类的质心并选择颜色的功能
- debugging - GAS 调试器在出错时立即关闭;关于调试的一些问题