如何在Android(客户端证书)中使用P12证书[英] How to use p12 certificates in Android (client certificates)

本文是小编为大家收集整理的关于如何在Android(客户端证书)中使用P12证书的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在尝试在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);
    }

  }

}

推荐答案

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

return new SSLSocketFactory(truststore);

SSLSocketFactory类具有其他构造函数,其中一个允许指定密钥库,密钥库密码和信托基地:

public SSLSocketFactory (KeyStore keystore, String keystorePassword, KeyStore truststore)(android.com/reference/reference/org/apache/http/http/conn/ssl/ssl/sssl/sssl/ssslsocketfactory.html#sssslslslslslsfactor; .

我不确定您是否可以将.P12文件加载为Android作为密钥库(可以在J2SE上).如果您不能,则必须将.P12文件转换为与您已经使用的信托店类似的充气城堡密钥库.使用该密钥存储创建您的SSLSocketFactory实例,您应该能够使用客户端证书.

通过Portecle将P12文件导入BK

创建BKS文件并导入现有.key+.pem文件非常简单,使用 portecle gui (Java程序).启动Portecle后,选择 file->新的键盘 - > bks .之后,您可以执行工具 - >导入密钥对并选择.P12文件. 最后保存使用您选择的密码保护的密钥存储.

本文地址:https://www.itbaoku.cn/post/102662.html

问题描述

I'm trying to use client certificates in android. I got a .p12 file that i want to use to authenticate towards the server.

I am using portecle to convert the .p12 file to a .bks file but i don't seem to get it to work.

Here's the code:

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);
    }

  }
}

What can i do to accomplish this?

UPDATE:

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);
    }

  }

}

推荐答案

The point where you have to change your code is when your new SSLSocketFactory instance:

return new SSLSocketFactory(truststore);

The SSLSocketFactory class has other constructors, one of them allows to specify a keystore, the keystore password and a truststure:

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

I am not sure if you can load your .P12 file under Android as KeyStore (on J2SE you can). If you can not you have to convert the .P12 file to a Bouncy castle keystore similar to the truststore you are already using. Use that key store to create your SSLSocketFactory instance and you should be able to use the client certificate.

Importing a P12 file into BKS via Portecle

Creating a BKS file and importing existing .key+.pem file is very simple using Portecle GUI (Java program). After starting Portecle select File -> New Keystore -> BKS. Afterwards you can execute Tools -> Import Key Pair and select the .P12 file. Finally save the key store protected with a password of your choice.