Creating self-signed certificates for use on Android

November 24th, 2011 by Marcus Krantz

A while ago I started to implement TLS/SSL mutual authentication on Android. How to actually implement the functionality on the Android platform is covered in my other article “Android – TLS/SSL Mutual Authentication”. Before such implementation can be done, it is important to have the keys and certificates prepared. In this article demonstrate how you can create these. However, this article is not just applicable to Android and should be usable in other scenarios as well.

For this article to be useful, the required tools are: openssl, Java’s Keytool and the BouncyCastle-provider (Click here to download). There are also some resources that I strongly recommend and has been very useful:

One might argue why I don’t use keytool to generate the keys and certificates and use them right away. Well, I was very curious about learning more about openssl and how to deal with various formats of keys and certificates.

1. Create private keys

Let’s start from scratch. First of all we need private keys. We use openssl to create these:

openssl genrsa -des3 -out client_key.pem 2048
openssl genrsa -des3 -out server_key.pem 2048

This will create the two keys; client.pem and server.pem. We will use these in the next step to sign our certificates with. In normal cases we would create a CA-signing request, that is sent to a CA who will issue your certificates. But since we want to self-sign our certificates this step is redundant.

2. Create self-signed certificates

openssl req -new -x509 -key client_key.pem -out client.pem -days 365
openssl req -new -x509 -key server_key.pem -out server.pem -days 365

Additionally, instead of being prompted for the certificate’s subject line you can use the <pre>-subj</pre> parameter and pass it to the <pre>openssl req</pre> command. What we just did was basically creating a CA signing request using our private keys to sign the outgoing x509-certificates. The certificates will be coded in pem-format and valid for 365 days.

3. Create trust stores

In order to use our keys and certificates in Java applications we need to import them into keystores. First of all, we want the client to trust the server certificate. To do this we must create a client trust store and import the server’s certificate.

keytool –importcert -trustcacerts –keystore clienttruststore.bks –storetype bks –storepass <truststore_password> -file server.pem -provider org.bouncycastle.jce.provider.BouncyCastleProvider –providerpath <path_to_bcprov_jar>

Note: On the client side, which in our case will be an Android app we use Bouncy Castle as our provider since it is supported on the Android platform.

Create a trust store for the server and import the client’s certificate into it.

keytool –importcert -trustcacerts –keystore  servertruststore.jks –storetype jks –storepass <server_truststore_password> -file client.pem

Currently, we have two trust stores one for the server in which we imported the client’s certificate and one for the client in which we imported the server’s certificate.

4. Combine keys and certificates

A problem with Java’s keytool application is that it won’t let us do such a simple thing as importing an existing private key into a keystore. The workaround to this problem is to combine the private key with the certificate into a pkcs12-file (which is understood by Java’s keytool) and then import this pkcs12 keystore into a regular keystore.

Combine the certificate and the private key for the server and client respectively:

openssl pkcs12 –export –inkey  client_key.pem –in client.pem –out  client.p12
openssl pkcs12 –export –inkey server_key.pem –in server.pem –out server.p12

5. Convert from pkcs12

Import the created keystores to new ones with common formats:

keytool –importkeystore –srckeystore client.p12 –srcstoretype pkcs12 –destkeystore client.bks –deststoretype bks –provider org.bouncycastle.jce.provider.BouncyCastleProvider –providerpath <path_to_bcprov_jar>
keytool –importkeystore –srckeystore server.p12 –srcstoretype pkcs12 –destkeystore server.jks –deststoretype jks

We should now have all files we need for a successful TLS/SSL mutual authentication. The files we move to our Android project will be: clienttruststore.bks and client.bks. The files we move to our server will be: servertruststore.jks and server.jks.

13 Responses to “Creating self-signed certificates for use on Android”

  1. Jamey says:

    Excellent post. Appreciate your time. One small comment: when copy-pasting to US locale, openssl fails because of character encoding. It seems to fail on the hyphens.

  2. Jamey says:

    looks like a type in Step 5: –destkeystoretype should be -deststoretype

  3. Marcus Krantz says:

    Hi Jamey, thank you for your comment. I have now updated step 5 in the instructions.

  4. Daniele Trabalza says:

    Hi,
    I found out that tis command is not working. Instead of “org.bouncycastleprovider….” should be “org.bouncycastle…”.

    This is the command that is working with BC 1.46:

    keytool –importcert -trustcacerts –keystore clienttruststore.bks –storetype bks –storepass -file server.pem -provider org.bouncycastle.jce.provider.BouncyCastleProvider –providerpath

  5. Marcus Krantz says:

    Hi Daniele, thanks for pointing it out. I have now updated the post.

  6. Fock says:

    Hi,

    I have the following errors when I’m trying to convert the client.p12 file on Windows :

    Exception: java.io.IOException: Error initialising store of key store: java.security.InvalidKeyException: Illegal key size.

    How can I solve it ?

  7. ladinho10 says:

    Your password lenght must be between 6 and 8 characters or follow the instructions on http://www.ngs.ac.uk/tools/jcepolicyfiles

  8. mail80 says:

    Hi,

    To which location on apache server the files viz: servertruststore.jks and server.jks to be moved/located.

  9. Hans says:

    managed to create the files and i think the Android part is working using the bks files.

    I have a C# server running in win7 how can i use the two
    servertruststore.jks and server.jks?
    Think i must import them into win7 keystore??

    /Thanks, Really easy and well written blog.

  10. Jestin Joy says:

    Getting this error on fourth step

    # keytool -importkeystore -srckeystore client.p12 -srcstoretype pkcs12 -destkeystore client.bks -deststoretype bks -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath /home/myname/Desktop/ssl_test/android/bcprov-jdk15on-147.jar
    Enter destination keystore password:
    Re-enter new password:
    Enter source keystore password:
    keytool error: java.io.IOException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded

    Please help

  11. Karol says:

    I followed all this steps.
    When I try to connect from Android to server I get:

    http-8443-2, SEND TLSv1 ALERT: fatal, description = bad_certificate
    http-8443-2, WRITE: TLSv1 Alert, length = 2
    http-8443-2, called closeSocket()
    http-8443-2, handling exception: javax.net.ssl.SSLHandshakeException: null cert chain

    But if I replace client.bks with client.p12 in Android application it works fine (of course I need to change KeyStore.getInstance(“bks”) to KeyStore.getInstance(“pkcs12″)).

    Any ideas why I’m having this problem?

  12. Hans says:

    What’s the point in having Android Client Certificates when the client cannot protect the password. The private key has the be unlocked with a password that the device have to carry with it or elsesome get.

    What you geeks think about that?

  13. Sadfeen says:

    Hi,
    Nice tutorial. I had to modify the step 4 to change the order of in and inkey arguments.
    Thanks.

Leave a Reply