java - SSLContext 和 PKCS12 keystore - 适用于 JVM 但不适用于 Android

标签 java android ssl

安卓版本:

    final SSLContext context = SSLContext.getInstance("TLS");
    final KeyStore keystore = KeyStore.getInstance("PKCS12");
    keystore.load(ctx.getAssets().open("ca_cli.pkcs12"), "password".toCharArray());
    final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    keyManagerFactory.init(keystore, "password".toCharArray());
    context.init(keyManagerFactory.getKeyManagers(), new TrustManager[] { new X509TrustManager() {
        @Override
        public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[] {}; }

        @Override
        public void checkClientTrusted(final X509Certificate[] arg0, final String arg1) throws CertificateException {
            // TODO Auto-generated method stub
        }

        @Override
        public void checkServerTrusted(final X509Certificate[] arg0, final String arg1) throws CertificateException {
            // TODO Auto-generated method stub
        }
    } }, new SecureRandom());

JVM 版本:

final SSLContext context = SSLContext.getInstance("TLS");
final KeyStore keystore = KeyStore.getInstance("pkcs12");
keystore.load(new FileInputStream(new File("ca-cli.pkcs12")), "password".toCharArray());
final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keystore, "password".toCharArray());
context.init(keyManagerFactory.getKeyManagers(), new TrustManager[] {
  new X509TrustManager() {
    @Override
    public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; }
    @Override
    public void checkClientTrusted(final X509Certificate[] arg0, final String arg1) throws CertificateException {
      // TODO Auto-generated method stub
    }
    @Override
    public void checkServerTrusted(final X509Certificate[] arg0, final String arg1) throws CertificateException {
      // TODO Auto-generated method stub
    }
  }
}, new SecureRandom());

代码完全相同,但 JVM 版本运行良好,Android 版本生成:

 09-16 12:24:17.024: E/AuthByPasswordLoader(14580): Got unexpected error
 09-16 12:24:17.024: E/AuthByPasswordLoader(14580):
  javax.net.ssl.SSLHandshakeException:
  javax.net.ssl.SSLProtocolException: SSL handshake terminated:
  ssl=0x656b0148: Failure in SSL library, usually a protocol error
 09-16 12:24:17.024: E/AuthByPasswordLoader(14580): error:14094410:SSL
  routines:SSL3_READ_BYTES:sslv3 alert handshake failure
  (external/openssl/ssl/s3_pkt.c:1290 0x40086500:0x00000003)

我已经尝试转换 PKCS12 -> BKS 但它没有帮助...

最佳答案

所以,如果有人遇到同样的问题 - 结果证明这是一个错误,在 Android 3.0 中引入。

引用 Kenny Root ( Android Security Discussion thread ):

Thanks, it looks like a bug that was introduced in Android 3.0. It will require that client key types have the same CA type. You are seeing this because your client certificate is RSA and the CA is EC.

You can work around this bug for your situation by wrapping the KeyManager and intercepting calls to chooseClientAlias to add "RSA_EC" to the keyTypes.

If you're interested in the particular fix that will be in a future release: https://android-review.googlesource.com/66581

关于java - SSLContext 和 PKCS12 keystore - 适用于 JVM 但不适用于 Android,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18824733/

相关文章:

java - 为什么我可以接收广播,但无法与应用程序中的特定套接字通信?

c# - 基础连接已关闭。服务器违反了协议(protocol)

node.js - 在不提供 SSL 证书的情况下运行 Node.js HTTPS 服务器?

java - 来自 pom.xml 的 Maven 解析器、Shrinkwrap

Java 程序跳过输入?

android - 如何重写 onCreateDialogView() 并在dialogpreference中添加自定义 View

javascript - 了解英特尔 XDK 中的图片处理

java - 在 Java (Swing) 中可以注册多个按键监听器事件吗?

java - 带背景的 Jframe.Jbutton

apache - 有没有办法用 HTTPS 加密主机头?