Prabhuraj
Prabhuraj

Reputation: 141

Configuring SSL client certificate in android app for client authentication in web server on tomcat

I installed apache server locally on my computer and running . I started with SSL server certificate for server authentication. To do this i added the server keystore path to the server.xml file of the tomcat and server certificate to truststore of SSL context in android app.Its working perfectly fine.

Now I need to configure the same for client authentication. For that I created a client keystore and stored that keystore in the resources/raw folder of android app and put that in keystore of the android app.

I created keystore for server and client using the below commands .

keytool -genkey -alias server -keyalg RSA -keystore server.jks
keytool -genkey -alias client -keyalg RSA -keystore client.jks
keytool -export -file server.cert -keystore server.jks -storepass password -alias server
keytool -export -file client.cert -keystore client.jks -storepass password -alias client

So i created 2 keystores , one for client and other for server , client.jks and server.jks . And i have client.cer and server.cer certificates exported from the corresponding keystore.

Client (Android application code) used to configure the SSL context . I have stored client.jks and server.cer files in the res/raw folder and referring that in the below code.

public HttpClient myHttpsClient() {
    HttpClient client = null;
    char[] passphrase = "password".toCharArray();

    try {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        CertificateFactory clientcf = CertificateFactory.getInstance("X.509");
        InputStream caInput = context.getResources().openRawResource(R.raw.server);
        InputStream clientcert = context.getResources().openRawResource(R.raw.client);
        Certificate ca;
        Certificate clientca;
        try {
            clientca = clientcf.generateCertificate(clientcert);
            ca = cf.generateCertificate(caInput);
            System.out.println("ca="+ ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
            clientcert.close();
        }
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStoreclient = KeyStore.getInstance(keyStoreType);
        keyStoreclient.load(null, null);
        keyStoreclient.setCertificateEntry("ca", clientca);


        // Create a KeyStore containing our trusted CAs
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);



        String kmfAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgorithm);
            kmf.init(keyStoreclient,passphrase);



        // Create a TrustManager that trusts the CAs in our KeyStore
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory
                .getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        MySSLSocketFactory socketFactory = new MySSLSocketFactory(context);//,new BrowserCompatHostnameVerifier());

        client = createHttps(socketFactory);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return client;

Now the server is configured as below .

<Connector SSLEnabled="true" acceptCount="100" clientAuth="false" truststoreFile="/Users/prabhuraj/client.cer" 
truststorePass="password" disableUploadTimeout="true" enableLookups="false" maxThreads="25"
port="8443" keystoreFile="/Users/prabhuraj/server.jks" keystorePass="password"
protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https"
secure="true" sslProtocol="TLS" />

After configuring as above. SSL handshake is failing . Can someone please let me know whether i am configuring wrongly? Thanks in advance.

Upvotes: 0

Views: 2412

Answers (1)

Than
Than

Reputation: 2769

You didnt use your KeyManagerFactory to init SSLContext,

change:

context.init(null, tmf.getTrustManagers(), null);

to

context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

However, your certificate used for client auth, will need it's private key. Look at this post for explaination: https://stackoverflow.com/a/11199270/2762154

Upvotes: 1

Related Questions