Pregunta

Estoy intentando usar certificados de cliente en Android. Obtuve un archivo .p12 que quiero usar para autenticar para el servidor.

Estoy usando Portecle para convertir el archivo .p12 en un archivo .bks, pero no parece que funcione.

Aquí está el código:

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

  }
}

¿Qué puedo hacer para lograr esto?

ACTUALIZAR:

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

  }

}
¿Fue útil?

Solución

El punto en el que debe cambiar su código es cuando su nueva instancia SSLSocketFactory:

return new SSLSocketFactory(truststore);

La clase SSLSocketFactory tiene otros constructores, uno de ellos permite especificar un almacén de claves, la contraseña del almacén de claves y una estación de confianza:

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

No estoy seguro de si puedes cargar tu .P12 Archivo en Android como almacén de claves (en J2SE puede). Si no puede tener que convertir el .P12 Presente a un almacén de claves de Castle Hearty similar a la tienda de confianza que ya está utilizando. Use esa tienda clave para crear su instancia SSLSocketFactory y debería poder usar el certificado del cliente.

Importar un archivo P12 a BKS a través de Portecle

Creando un BKS archivo y importación de existentes .key+.pem El archivo es muy simple usando GUI de Portecle (Programa Java). Después de iniciar Portecle Seleccione Archivo -> Nuevo almacén de claves -> BKS. Después puede ejecutar Herramientas -> Importar el par de claves y seleccione el .P12 expediente. Finalmente, guarde el almacén de claves protegido con una contraseña de su elección.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top