2

我正在尝试在 android 中使用客户端证书。我有一个 .p12 文件,我想用它来对服务器进行身份验证。

我正在使用 portecle 将 .p12 文件转换为 .bks 文件,但我似乎没有让它工作。

这是代码:

package com.pa1406.SECURE;

import java.io.InputStream;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;

import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.SingleClientConnManager;

import android.content.Context;

public class HttpsClient extends DefaultHttpClient {

  final Context context;

  public HttpsClient(Context context) {
    this.context = context;
  }

  @Override protected ClientConnectionManager createClientConnectionManager() {
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(
        new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(
        new Scheme("https",newSslSocketFactory(), 443));
    return new SingleClientConnManager(getParams(), registry);
  }

  private SSLSocketFactory newSslSocketFactory() {
    try {
      KeyStore truststore = KeyStore.getInstance("BKS");

      InputStream in = context.getResources().openRawResource(R.raw.keystore);

      try {
          truststore.load(in, "qwerty1234".toCharArray());
      } finally {
        in.close();
      }
      return new SSLSocketFactory(truststore);
    } catch (Exception e) {
      throw new AssertionError(e);
    }

  }
}

我该怎么做才能做到这一点?

更新:

package com.pa1406.SECURE;


import java.io.InputStream;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;

import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.SingleClientConnManager;

import android.content.Context;

public class HttpsClient extends DefaultHttpClient {

  final Context context;

  public HttpsClient(Context context) {
    this.context = context;
  }

  @Override protected ClientConnectionManager createClientConnectionManager() {
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(
        new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    registry.register(
        new Scheme("https",newSslSocketFactory(), 443));
    return new SingleClientConnManager(getParams(), registry);
  }

  private SSLSocketFactory newSslSocketFactory() {
    try {
        // setup truststore to provide trust for the server certificate

        // load truststore certificate
        InputStream clientTruststoreIs = context.getResources().openRawResource(R.raw.truststore);
        KeyStore trustStore = null;
        trustStore = KeyStore.getInstance("BKS");
        trustStore.load(clientTruststoreIs, "qwerty1234".toCharArray());

        System.out.println("Loaded server certificates: " + trustStore.size());

        // initialize trust manager factory with the read truststore
        TrustManagerFactory trustManagerFactory = null;
        trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);

        // setup client certificate

        // load client certificate
        InputStream keyStoreStream = context.getResources().openRawResource(R.raw.torbix);
        KeyStore keyStore = null;
        keyStore = KeyStore.getInstance("BKS");
        keyStore.load(keyStoreStream, "qwerty1234".toCharArray());

        System.out.println("Loaded client certificates: " + keyStore.size());

        // initialize key manager factory with the read client certificate
        KeyManagerFactory keyManagerFactory = null;
        keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, "qwerty1234".toCharArray());

     // initialize SSLSocketFactory to use the certificates
        SSLSocketFactory socketFactory = null;
        socketFactory = new SSLSocketFactory(SSLSocketFactory.TLS, keyStore, "qwerty1234",
            trustStore, null, null);

      return socketFactory;
    } catch (Exception e) {
      throw new AssertionError(e);
    }

  }

}
4

1 回答 1

4

您必须更改代码的地方是您的新 SSLSocketFactory 实例:

return new SSLSocketFactory(truststore);

SSLSocketFactory 类还有其他构造函数,其中一个允许指定密钥库、密钥库密码和信任:

public SSLSocketFactory (KeyStore keystore, String keystorePassword, KeyStore truststore)( JavaDoc )

我不确定您是否可以.P12在 Android 下将文件加载为 KeyStore(在 J2SE 上可以)。如果不能,则必须将.P12文件转换为类似于您已经使用的信任库的 Bouncy Castle 密钥库。使用该密钥库创建您的 SSLSocketFactory 实例,您应该能够使用客户端证书。

通过 Portecle 将 P12 文件导入 BKS

使用Portecle GUI(Java 程序)创建BKS文件和导入现有.key+.pem文件非常简单。启动 Portecle 后,选择File -> New Keystore -> BKS。之后您可以执行工具 -> 导入密钥对并选择文件。最后保存使用您选择的密码保护的密钥库。.P12

于 2011-11-29T14:00:45.680 回答