【问题标题】:Android 6 can not communicate with secured server using Self Sign CertificateAndroid 6 无法使用自签名证书与安全服务器通信
【发布时间】:2017-06-08 11:57:27
【问题描述】:

我无法在 Android 6 应用程序和安全服务器之间建立连接,其中服务器使用 Java (jdk 1.6) keytool 命令生成的自签名证书。 Android 6 应用显示以下错误。

异常日志:

javax.net.ssl.SSLHandshakeException: Handshake failed : javax.net.ssl.SSLHandshakeException: Handshake failed
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.Connection.connectTls(Connection.java:235)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.Connection.connectSocket(Connection.java:199)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.Connection.connect(Connection.java:172)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:367)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:130)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:329)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:246)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:457)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:126)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:257)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218)
05-23 17:21:03.498 3602-6487/issac.wise.pay I/System.out:     at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java)

我正在使用下面的代码,它在 android 5.9 之前运行良好,但它不适用于 android 6(marshmallow);以下链接提供了与 ssl 通信的代码 -

https://developer.android.com/training/articles/security-ssl.html

// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
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();
}

// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);

// Tell the URLConnection to use a SocketFactory from our SSLContext
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);

有人可以建议如何解决这个问题吗?这是任何证书生成问题还是我需要遵循任何新技术与服务器通信?

【问题讨论】:

  • “它在 android 5.9 之前运行良好”——没有 Android 5.9。 “以下链接提供了与 ssl 通信的代码”——这不是您的代码,除非您尝试与华盛顿大学 CA 测试服务器通信。相反,这似乎是您从the documentation 复制的代码。除非我们能看到 your 代码,否则我们无法帮助您解决 youryour 代码有关的问题。
  • “这是任何证书生成问题还是我需要遵循任何新技术与服务器通信?” ——我想不出Android 6.0有什么变化。 Android 的 network security configuration 在这里提供了新选项,但这是 Android 7.0 的新选项,尽管 I have backported it to Android 4.2

标签: android ssl android-6.0-marshmallow self-signed


【解决方案1】:

Android 6 不再接受不安全的连接,您应该使用安全证书或通过让应用忽略不安全证书来解决此问题(这会产生严重的安全问题,完全不推荐)。

来自 Android 开发者:https://developer.android.com/training/articles/security-ssl.html

自签名服务器证书 SSLHandshakeException的第二种情况是由于自签名证书,这意味着 服务器表现为自己的 CA。这类似于未知 证书颁发机构,因此您可以使用与 上一节。

您可以创建自己的 TrustManager,这次信任服务器 直接发证书。这具有前面讨论的所有缺点 将您的应用程序直接绑定到证书,但可以安全地完成。 但是,您应该小心确保您的自签名 证书具有相当强的密钥。截至 2012 年,2048 位 RSA 每年到期的指数为 65537 的签名是可以接受的。 轮换密钥时,您应该检查来自 关于什么是可接受的权威(例如 NIST)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 2014-08-08
    • 2013-08-23
    • 1970-01-01
    相关资源
    最近更新 更多