Sunday, November 2, 2008

J2ME MIDlet signing process using own Certificate Authority (CA)

Introduction

The Java Platform is very well known as very powerful and reliable software development platform. However, sometimes it's difficult to get started using some of its feature. The purpose of this article is to show how to sign J2ME MIDlet using custom CA , deploy and test it on a mobile phone. The process will be demonstrated using HTC phone which allows installation of custom root certificates. We will generate an intermidiate certificate signed by the root certificate and intended to represent our imaginary company ByMobile. Users will have to install the root certificate into their mobile phones manually as described below.

Other phones (for example Sony Ericsson K550i) may not allow you to install such custom root certificate, so you'll have to sign your intermidiate sertificate using VeriSign which will cost you some money. This will work because VeriSign has preinstalled root cetificates on most mobile phones (like Sony Ericsson), so you don't have to worry about users installing them separately.

This article will be largely based on several others. The first part will be similar to one described in HOWTO Build, Sign and Install MIDlets. That article was written a couple of years ago and some of the tools are not available any more. Some of the steps and build scripts will be based on ones described in MIDlet jar signing (a tutorial) Revised.

Environment

Ubuntu Linux 8.4, Sun JDK 1.6.0_07, WTK 2.5.2, IntelliJ IDEA 8.0 (build 8664), HTC Touch Dual (Windows Mobile 6 Professional), OpenSSL 0.9.8i, antenna 1.1.0-beta and preprocessor-v3-1.2

Step 1

Ok, let's get started. One of our main subtasks is to enable our imaginary company ByMobile to sign MIDlet's. For that we need a public/private key pair and a certificate which include our public key and will be signed by trusted CA (for example VeriSign or our custom CA).

So. the first thing we need to do is to generate a public/private key pair (see full description of the tool at keytool-Key and Certificate Management Tool):

keytool -genkey -alias code-sign -keyalg RSA -validity 365 -keystore code-sign.ks

We'll need to enter our keystore password (which will be passwd in this example) twice to create our new keystore.

Then we need to enter:

name = AndriiNeverov

unit = Dev

org = ByMobile

city = Lyngby

state = Copenhagen

country = DK

Confirm and enter key's password which will be the same as keystore's one in this example.

Now we can check if the key was actually created:

keytool -list -keystore code-sign.ks

which gives us:

Keystore type: JKS

Keystore provider: SUN

Your keystore contains 1 entry

code-sign, Nov 2, 2008, PrivateKeyEntry,

Certificate fingerprint (MD5): 4B:60:3E:24:64:4E:0D:C3:E7:D3:07:A2:EE:72:CE:CB

The next thing we need to do is to generate certificate requst to be able to give our signed certificate to users to verify our signatures:

keytool -certreq -alias code-sign -keystore code-sign.ks -storepass passwd -keypass passwd -file code-sign-request-PKCS10.csr

This gives us file code-sign-request-PKCS10.csr which we need to send to the trusted CA (for xample VeriSign) for signature. For the purpose of this article we will create our own trusted CA.

Step2

Create a key for our CA:

openssl genrsa -des3 -out ca-key.key 4096

Enter our password (passwd) twice. Now we have a key stored in ca-key.key

Generate CA public certificate in DER format:

openssl req -new -x509 -days 365 -key ca-key.key -outform DER -out ca-cert-DER-PKCS10.cer

Enter password.

Enter:

county = DK

state = Copenhagen

city = Lyngby

company = ByMobile

unit = Headquaters

common name = ByMobileRootCert

email =

Generate CA public certificate in PEM format:

openssl req -new -x509 -days 365 -key ca-key.key -out ca-cert-PEM-PKCS10.crt

Repeat the same information as the above.

Step 3

Sign certificate request with created root certificate. The result is an intermidiate certificate which represents our imaginary company's public key:

openssl x509 -req -days 365 -in code-sign-request-PKCS10.csr -CA ca-cert-PEM-PKCS10.crt -CAkey ca-key.key -set_serial 01 -out code-sign-cert-PEM-X509.crt

Enter passwd.

The result is leaf certificate code-sign-cert-PEM-X509.crt. However, leaf certificate is NOT valid without root certificate by which it's signed. So, we need to combine both certificates together.

Step4

Now we need to combine root certificate and our leaf certificate in one file in PKCS#7 format.

  1. Open Internet Explorer

  2. Open certificate manager (Tools->Internet Options->Content->Certificates)

  3. Pick “Trusted Root Certification Authorities” tab and Click “Import”

  4. Click “Next” and choose path to your ca-cert-PEM-PKCS10.crt file and click “Next”

  5. Pick certificate store as “Trusted Root Certification Authorities” and continue until it says imported.

  6. Now pick “Intermediate Certification Authorities” tab import certificate code-sign-cert-PEM-X509.crt like you did for ca-cert-PEM-PKCS10.crt. Once successfully imported, you’ll see the code-sign certificate among intermediate certificates.

  7. In “Intermediate Certification Authorities” select your code-sign certificate and click “Export”

  8. Succeeding screen will prompt you to choose the format. Pick PKCS#7 (.P7B). and check “include all certificates in the certification path if possible” checkbox (very important)

  9. Continue by clicking next and pick a file name (say code-sign-combined-PKCS7.p7b)

  10. Continue till it says successfully exported and you should see a file by name code-sign-combined-PKCS7.p7b has been created.

Important: Pay special attention to step 8, If you do not check "include all certificates..." you will not be able to sign your MIDlet.

Step 5

Now it's time to install our combined reply back to the keystore. It's better to mak a backup copy of your keystore in case something goes wrong. This is very important step and we need to install reply to exactly the same alias as we used to generate a public/private key pair for our imaginary company:

keytool -import -alias code-sign -keystore code-sign.ks -file code-sign-combined-PKCS7.p7b

... is not trusted. Install reply anyway? [no]: yes

Certificate reply was installed in keystore

Step 6

Ok, now as we have our intermidiate certificate in the keystore and we're ready to sign our test MIDlet.

Test project consists of 4 sub-projects:

  • Simple – MIDlet which shows Java logo image which is stored locally as a resource. Intended to verify that deployment actually works.
  • Untrusted – MIDlet which shows Java logo image obtained from Internet. Intended to verify that all network access attempts are controlled by JAM.
  • Trusted – MIDlet which shows Java logo image obtained from Internet and is signed by our imaginary company. Intended to verify that all network access attempts are permitted
  • Web – web application which allows user to download midlets and root certificate via OTA.
Here is what you need to do:
  1. Open project in IDEA
  2. Rebuild project
  3. Copy Simple.jad and Simple.jar from Simple to Web/web (near index.jsp)
  4. Copy Untrusted.jad and Untrusted.jar from Untrusted to Web/web (near index.jsp)
  5. Add references to antenna and preprocessor for IDEA's Ant
  6. Run deploy task
  7. Copy Trusted.jad and Trusted.jar from MIDletSigningTest/out/signed to Web/web (near index.jsp)
  8. Refresh Web module
  9. Copy Security/ca-cert-DER-PKCS10.cer from Trusted to Web/web (near index.jsp)
  10. Rebuild project

Now we can test it using WTK's emulator:

  1. Run ktoolbar
  2. File > Create project form JAD/JAR
  3. Select MIDletSigningTest/out/signed/Trusted.jad
  4. File > Utilities > Manage Certificates
  5. Import certificate > Security/ca-cert-DER-PKCS10.cer from Trusted > Manufacturer
  6. Close
  7. Close
  8. Project > Run via OTA

Check whether it works. Although Sun's emulator sometimes seems like fragile, my experience shows that if something doesn't run inside it, it will most likely have problem in real phone.

Let's check it on a real mobile phone (HTC, WM6):

1. Deploy MIDletSigningTest/out/Web.war to some server (I recommend eatj.com, because it's free and quite decent Java web hosting )

2. Go to your server (I did this with a page on eatj.com)

3. Install Simple

Notice that it asks whether to install untrusted MIDlet

4. Run it

5. Install Untrusted

Notice that it asks whether to install untrusted MIDlet

Notice that it asks whether to transfer data from network

Notice that it asks whether to allow net access and there are two options:

  • ask me next session
  • ask me next time

6. Install Trusted

Notice that it fails with message like “The root certificate used for Trusted cannot be found”

7. Click on Root Certificate ByMobile CA and check "Open file after download"

Notice that it says that one or more certificates were installed successfully

8. Install Trusted

Notice that it says that Trusted is signed by ByMobile, DK

Notice that it asks for Connector.http permissions (it's important to state necessary permissions explicitly, otherwise it will install, but fails later)

Notice that it asks whether to transfer data from network

Notice that it asks whether to allow net access and there are two options:

  • don't ask
  • ask me next session
  • ask me next time

If you chose don't ask, it will never ask again for this app, even after phone restart

Go to Notice in Settings > System > Certificates > Root

the last certificate is the Root Cert ByMobile CA

Conclusion

As we can see Java Platform plays very well with all standards including those related to security. Using described techniques you should be able to leverage the full power of Java on your mobile phones as much as you do on the server side or desktops. Although the setup may seem to be a bit complex, the problem is solvable using a set of flexible tools available out there. This is a common pattern with Java. I hope this document and provided build scripts help you to build your mobile applications quickly and efficiently.

Enjoy your signed mobile applications! ;)

TODO

  1. Update certificates combining process to be performed using OpenSSL instead of IE.
  2. Provide central Ant build script to eliminate all the manual steps and make the process to be fully automated.