【发布时间】:2018-03-14 15:40:07
【问题描述】:
我正在尝试使用 BouncyCastle (SpongyCastle) 库在运行 Jellybean 4.1.2 的旧 Android 设备上登录我的 TLS1.2 服务器,但它不起作用。该版本的 Android 默认没有启用 TLS,所以我需要 3rd 方库才能使用它。
有两个问题。 1. 我收到的是 HTTP 302 而不是 JSON 响应。 2. 我不知道如何发送 JSON 有效负载(对于我将使用的其他端点
使用 HTTP 302,我得到以下响应:
Result: HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Cache-Control: private
Expires: Thu, 01 Jan 1970 00:00:00 UTC
Set-Cookie: JSESSIONID=83C535625CDEF9DEC3D7890F1A9C86B0; Path=/; Secure; HttpOnly
Location: https://www.google.com/login/auth Content-Length: 0
Date: Wed, 14 Mar 2018 15:32:19 GMT
Via: 1.1 google
Set-Cookie: GCLB=CMfzgbfeh7bLpwE; path=/; HttpOnly
Alt-Svc: clear
Connection: close
所以它似乎试图重定向到某种谷歌登录,这很奇怪。
另外,对于上面的数字 2,我尝试发送有效负载,我是添加另一个 output.write(myJSONPayload); 还是必须做其他事情?
我的代码如下:
{
java.security.SecureRandom secureRandom = new java.security.SecureRandom();
Socket socket = new Socket("www.myserver.com", 443);
TlsClientProtocol protocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(), secureRandom);
DefaultTlsClient client = new DefaultTlsClient() {
public TlsAuthentication getAuthentication() throws IOException {
TlsAuthentication auth = new TlsAuthentication() {
// Capture the server certificate information!
public void notifyServerCertificate(Certificate serverCertificate) throws IOException {
}
public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
return null;
}
};
return auth;
}
};
protocol.connect(client);
java.io.OutputStream output = protocol.getOutputStream();
output.write("GET / HTTP/1.1\r\n".getBytes("UTF-8"));
//Get auth with my own class to generate base 64 encoding
output.write(("Authorization: " + BasicAuthentication.getAuthenticationHeader("myuser", "mypass")).getBytes());
output.write("Host: www.myserver.com/logon\r\n".getBytes("UTF-8"));
output.write("Connection: close\r\n".getBytes("UTF-8")); // So the server will close socket immediately.
output.write("\r\n".getBytes("UTF-8")); // HTTP1.1 requirement: last line must be empty line.
output.flush();
java.io.InputStream input = protocol.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String line;
StringBuilder sb = new StringBuilder();
try {
while ((line = reader.readLine()) != null) {
Log.d(TAG, "--> " + line);
sb.append(line).append("\n");
}
} catch (TlsNoCloseNotifyException e) {
Log.d(TAG, "End of stream");
}
String result = sb.toString();
Log.d(TAG, "Result: " + result);
}
另一个问题,我是否指定了正确的主机?我在Socket 中有基本 URL,在OutputStream 中有完整 URL 是否正确?
【问题讨论】:
-
你为什么不使用 HTTP 类?
-
我的服务器只有 TLS1.2。从 Android Jellybean 到 KitKat,默认不启用 TLS1.2。我尝试在使用普通 HTTP 类(覆盖 SSLFactory 等)时启用它,但我无法让它工作。我尝试了 bouncycastle,它似乎第一次工作,所以我只需要让 bouncycastle 使用我现有的代码。
-
“HTTP 类”我假设你的意思是内置的 Android
HTTPSURLConnection类等? -
BouncyCastle 的最新版本包括一个 JSSE 提供程序(“BCJSSE”)。我相信 SpongyCastle 现在也在 tls 模块中重新打包(作为“SCJSSE”)。原则上,您可以在默认提供者之前注册这个备用 JSSE 提供者,HttpsURLConnection 应该使用它。
-
是的,除了它是一个独立于普通加密的提供程序类 - org.bouncycastle.jsse.provider.BouncyCastleJsseProvider(并且它在一个单独的 jar - tls 中)。
标签: android bouncycastle tls1.2 spongycastle