Android上SSLv3握手失败不一致

3
我正在开发一个处理食品订单的应用程序,我们通过HttpsURLConnection将请求发送到已经进行SSL认证的php函数。我遇到的问题是它有时会拒绝握手,有时不会。我想知道是否有人能够解释一下为什么会有一次拒绝而另一次不会。

javax.net.ssl.SSLProtocolException: SSL握手中止: ssl=0x56cbe008:SSL库中的故障,通常是协议错误 error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:744 0x52eb6d74:0x00000000) javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL握手中止: ssl=0x56cbe008:SSL库中的故障,通常是协议错误 error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:744 0x52eb6d74:0x00000000)

url = new URL(request.endpointUri);

Log.d(LOG_TAG, "Opening connection to " + request.endpointUri);
conn = (HttpsURLConnection)url.openConnection();

//setup the connection
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("charset", "UTF-8");
conn.setDoInput(true);
conn.setDoOutput(true);

//setup the parameters
Uri.Builder params = new Uri.Builder();
String paramString;

params.appendQueryParameter("cctoken", request.token.getId());
params.appendQueryParameter("amt", Integer.toString(request.order.amount));
params.appendQueryParameter("email", request.order.customerEmail);
params.appendQueryParameter("order", request.order.details);

paramString = params.build().getEncodedQuery();
conn.setFixedLengthStreamingMode(paramString.getBytes("UTF-8").length);

Log.d(LOG_TAG, "Compiled query into: " + paramString);

//write the POST request params
OutputStream os = conn.getOutputStream();
BufferedWriter streamWriter = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
streamWriter.write(paramString);
streamWriter.flush();
streamWriter.close();
os.close();

//read the response
int responseCode = conn.getResponseCode();
InputStream is;

尝试收集输出时出现错误的代码行。
OutputStream os = conn.getOutputStream();
3个回答

4
SSL握手错误有时只与服务器端问题相关,因此您的代码在这里没有太大帮助。服务器端可能的原因是多个具有不同配置的服务器(有些工作,有些不工作),由于负载过重而导致的超时,服务器端崩溃。还可能涉及一些不稳定的中间件(防火墙),或者如果连接从一开始就不可靠,也会影响SSL握手。
因此,请不要过多关注您的代码,而是关注服务器和网络。如果有疑问,请尝试另一个客户端,如果此客户端显示更稳定的行为,请查看连接和SSL握手之间的差异(即数据包捕获)。

1
这个问题可能是由于您发送请求的服务器的自签名证书引起的。您需要执行类似以下操作: `//从InputStream加载CAs //(可以来自资源、ByteArrayInputStream等)`
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt

InputStream caInput = new BufferedInputStream(new FileInputStream("load-   der.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}

// 创建一个包含受信任CA的密钥库

String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// 创建一个信任管理器,信任我们密钥库中的CA证书
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// 创建一个使用我们的TrustManager的SSLContext
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

//告诉URLConnection使用来自我们SSLContext的SocketFactory

URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);`

Found it here

可以翻译为:

{{链接1:在这里找到它}}


1

相关问题:客户端和服务器不支持共同的加密协议

如果错误信息显示类似以下内容:

error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0x8d92d990:0x00000000)

(请注意,在“GET_SERVER_HELLO:”之后,它说“tlsv1”,而不是“sslv3”。)这是一个微弱的线索,表明问题可能与所需的加密版本有关。如果客户端过旧,则可能仅支持sslv2或sslv3。最新的服务器可能支持TLS1.2,并且不支持较旧的(可能已弃用的)ssl版本。反之亦然,服务器仅支持旧版本,客户端仅支持新版本也是可能的。

我遇到了一个旧版的Android Jelly Bean客户端的问题,它默认不支持HttpsUrlConnection的TLS1.2。通过创建TLSSocketFactory和X509TrustManager,并调用setSSLSocketFactory(),我可以让旧版本的Android使用TLS1.2,这使得服务器很高兴。Navneet Krishna在https://medium.com/@krisnavneet/how-to-solve-sslhandshakeexception-in-android-ssl23-get-server-hello-tlsv1-alert-protocol-13b457c724ef中写了一个很好的描述如何做到这一点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接