2

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

  }

}
Bewn
  • 575
  • 4
  • 9
  • 13

1 Answers1

4

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.

Robert
  • 39,162
  • 17
  • 99
  • 152
  • I tried to use the .p12 file but it didn't work, need to convert it. I'm not sure if i'm doing right. I'll update the question so you can se were i am now. – Bewn Nov 29 '11 at 14:15
  • For converting P12->BKS I would use the tool [Portecle](http://portecle.sourceforge.net) - if you prefer a GUI instead of a command-line. – Robert Nov 29 '11 at 14:19
  • That's what i am using, how do i do to convert it? Do i open .p12 with portecle and export the key and the certificate and then add them to my new keystore or should i do something else? :) – Bewn Nov 29 '11 at 14:21
  • I'm also struggling to find out how to convert a P12 -> BKS in Portecle, any ideas? – Andy Davies Jul 09 '12 at 11:05