Как использовать сертификаты p12 в Android (клиентские сертификаты) - PullRequest
1 голос
/ 29 ноября 2011

Я пытаюсь использовать клиентские сертификаты в 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);
    }

  }
}

Что я могу сделать, чтобы достичь этого?

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

  }

}

1 Ответ

3 голосов
/ 29 ноября 2011

Точка, в которой вы должны изменить свой код, - это когда ваш новый экземпляр SSLSocketFactory:

return new SSLSocketFactory(truststore);

У класса SSLSocketFactory есть другие конструкторы, один из которых позволяет указать хранилище ключей, пароль хранилища ключей и доверенное отношение:

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

Я не уверен, что вы можете загрузить файл .P12 под Android как KeyStore (на J2SE вы можете).Если вы не можете, вам нужно конвертировать файл .P12 в хранилище ключей Bouncy castle, похожее на хранилище доверенных сертификатов, которое вы уже используете.Используйте это хранилище ключей для создания экземпляра SSLSocketFactory, и вы сможете использовать сертификат клиента.

Импорт файла P12 в BKS через Portecle

Создание BKS файл и импорт существующего .key + .pem файла очень прост, используя Portecle GUI (Java-программа).После запуска Portecle выберите Файл -> Новое хранилище ключей -> BKS .После этого вы можете выполнить Инструменты -> Импортировать пару ключей и выбрать файл .P12.Наконец, сохраните хранилище ключей, защищенное выбранным паролем.

...