How to Encrypt Data in Java ME Applications Using the SATSA API

By Bruce Hopkins

Knowing how and when to properly use security techniques is a skill that every Java ME developer needs to possess. Over the coming months (and years for that matter), an increasing number of mobile devices will support the Mobile Service Architecture (MSA) specification, which was a huge milestone for mobile devices. The MSA includes a bevy of mobile Java specifications, including the Security and Trust Services API (SATSA).

SATSA allows mobile developers to perform the following secure functions:
  • Encrypt and decrypt data using standard encryption algorithms like 3DES and AES
  • Create, sign, and verify digital signatures
  • Create symmetric and asymmetric keys
  • Interact with the security element included on the mobile device

The encryption APIs built into SATSA (also known as SATSA-Crypto) is modeled after the encryption APIs built into the JDK 1.4, Thus, techniques that you learn in this tech tip can be used elsewhere.

In this tech tip, I’m going to assume that you have no background in encryption technologies. So let’s understand the difference between symmetric and asymmetric cryptography. Look at the following figure:

Symmetric Cryptography

As you can see, in symmetric cryptography, the same key that encrypts your data is also the key that decrypts it. This facet of symmetric cryptography limits its use to a certain set of use cases. Symmetric cryptography is fine if you want to encrypt data for your own use, but it is definitely not a good solution if you need other people to send data securely to you. You can’t afford to have your security compromised, so sharing your symmetric key with other parties is not a good idea.

The following image, however, shows how asymmetric cryptography solves the problem:

Asymmetric Cryptography

With asymmetric cryptography, there are two keys involved instead of one. The first key (called the public key) can only secure or encrypt your data (it can never be used to decrypt the data). The second key (called the private key) can only be used to decrypt the data (and it can’t used to encrypt the data). For securing data for your own use, asymmetric cryptography is probably overkill. If you are communicating with several parties and they need to send data securely to you, however, then you can freely give them (or anyone else for that matter) your public key. It can be used only to encrypt data that can be decrypted only by you. You ,of course, keep the private key to yourself.

In this example, we are going to use 3DES symmetric encryption to show how to encrypt and decrypt some plain strings. Here’s how I create the key:

    // 24 byte symmetric 3DES-EDE key
    byte[] symKey = {
      (byte) 0xca, (byte) 0x00, (byte) 0x25, (byte) 0x06,
      (byte) 0x28, (byte) 0xae, (byte) 0xd2, (byte) 0xbd,
      (byte) 0x2b, (byte) 0x7e, (byte) 0x15, (byte) 0x16,
      (byte) 0x28, (byte) 0xae, (byte) 0xd2, (byte) 0xa6,
      (byte) 0x2c, (byte) 0x7e, (byte) 0x10, (byte) 0x96,
      (byte) 0x28, (byte) 0xff, (byte) 0xd2, (byte) 0xa6,
    };

As you can see, I simply created a byte array of length 24 with an assortment of bytes to create my key. There is no special sequence needed, just an array of 24 bytes. In the example code, be sure to change byte values in this array to see how the key affects outcome of the encrypted text.

The following lines show how to create the actual Key and Cipher objects:

Key encryptionKey = new SecretKeySpec(symKey, 0, symKey.length, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");

As you can see, the last parameter in the SecretKeySpec constructor shows that an encryption algorithm must be supplied. I’ve already stated that I’m going to use the 3DES algorithm in this example, so I also have to supply the String that represents that encryption algorithm, “DESede”. The encryption algorithm must also be specified to get new instances from the Cipher class. In this case, however, I also had to specify the block character and padding modes. Once you have the key and Cipher, then encrypting data is a piece of cake:

   cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
   byte[] ciphertext = new byte[ciphertextLength];
   cipher.doFinal(messageBytes, 0, messageBytes.length, ciphertext, 0);

Decrypting data is also very easy; just change the Cipher mode:

  cipher.init(Cipher.DECRYPT_MODE, encryptionKey);
  byte[] decrypted = new byte[messageBytes.length];
  cipher.doFinal(ciphertext, 0, ciphertext.length, decrypted, 0);
  

The following complete working example runs on the Sun Wireless Toolkit for CLDC and also on SATSA-enabled mobile devices:

import java.security.\*;
import java.security.spec.\*;

import javax.crypto.\*;
import javax.crypto.spec.\*;

import javax.microedition.lcdui.\*;
import javax.microedition.midlet.\*;

public class EncryptionTest extends MIDlet implements CommandListener, Runnable {

    // 24 byte symmetric 3DES-EDE key
    byte[] symKey = {
      (byte) 0xca, (byte) 0x00, (byte) 0x25, (byte) 0x06,
      (byte) 0x28, (byte) 0xae, (byte) 0xd2, (byte) 0xbd,
      (byte) 0x2b, (byte) 0x7e, (byte) 0x15, (byte) 0x16,
      (byte) 0x28, (byte) 0xae, (byte) 0xd2, (byte) 0xa6,
      (byte) 0x2c, (byte) 0x7e, (byte) 0x10, (byte) 0x96,
      (byte) 0x28, (byte) 0xff, (byte) 0xd2, (byte) 0xa6,
    }; 

    private Display display;
    private Form startForm;
    private Command exitCommand;

    public EncryptionTest() {
        exitCommand = new Command("Exit", Command.EXIT, 0);

        startForm = new Form("Encryption Example");
        startForm.append("");
        startForm.addCommand(exitCommand);
        startForm.setCommandListener(this);
    }

    public void startApp() {
        display = Display.getDisplay(this);
        display.setCurrent(startForm);

        Thread t = new Thread(this);
        t.start();
    }

    public void pauseApp() {
    }

    public void destroyApp(boolean unconditional) {
    }

    public void commandAction(Command command, Displayable s) {
        if (command == exitCommand) {
            notifyDestroyed();
        }
    }

    public void run() {
        try {
		encryptAndDecrypt("This is string with some text");
            encryptAndDecrypt("ID: 2341234");
            encryptAndDecrypt("PIN: 0001"); 

	  } catch (Exception e) {
		System.out.println(e.toString());

        }

    }


    private void encryptAndDecrypt(String plainText)
        throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException,
            InvalidKeyException, IllegalStateException, ShortBufferException,
            IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {

	   byte[] messageBytes = plainText.getBytes();
	   print("Plain text: " + plainText);

         // Create the symmetric encryption Key 
         Key encryptionKey = new SecretKeySpec(symKey, 0, symKey.length, "DESede");

         /\* Construct Cipher class with name of the transformation algorithm \*/
	   Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");

        // Calculate ciphertext size.
        int blocksize = 16;
        int ciphertextLength = 0;
        int remainder = messageBytes.length % blocksize;

        if (remainder == 0) {
            ciphertextLength = messageBytes.length;
        } else {
            ciphertextLength = messageBytes.length - remainder + blocksize;
        }
	  System.out.println("ciphertext length: " + ciphertextLength);

        cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
        byte[] ciphertext = new byte[ciphertextLength];
        cipher.doFinal(messageBytes, 0, messageBytes.length, ciphertext, 0);
        print("Encrypted text: " + new String(ciphertext));

	  cipher.init(Cipher.DECRYPT_MODE, encryptionKey);
        byte[] decrypted = new byte[messageBytes.length];
        cipher.doFinal(ciphertext, 0, ciphertext.length, decrypted, 0);
	  print("the decrypted text is: " + new String(decrypted));


    }

    private void print(String s) {
	  startForm.append(s);
    }
}
Bruce Hopkins is the author of the book, Bluetooth for Java (Apress Publishers), and is the creator of the JB-22 developer kit.
Comments:

Hi,

I´ve found this post very helpfull to understand how to encrypt and decrypt data in J2ME, but I have one question:
Do you know some method to obtain the key from a given password instead of define it statically? I mean, do you know some method to do a Password-based encryption (PBE) with SATSA API?

Posted by David on February 13, 2008 at 11:36 PM PST #

3DES working on only netbeen ,not working on mobile

Posted by M.Alagar raja on February 14, 2008 at 02:48 PM PST #

David and all,

Although SATSA may not support PBE, the Bouncy Castle library for J2ME supports PBE:

http://www.bouncycastle.org/specifications.html

Thanks,

Bruce

Posted by Bruce Hopkins on February 15, 2008 at 03:30 AM PST #

Hi ,any one can help me to encrpt plain text 26 bit key in cipher text, and reverse.
i NEED a fullworking program in jsp or j2m3 or php ................................................thx

Posted by Muhammad Qasim Rafique on April 13, 2008 at 05:32 AM PDT #

Muhammad,

The code that I presented above in this Tech Tip shows how to encrypt and decrypt data using J2ME. What else are you looking for?

Thanks,

Bruce

Posted by Bruce Hopkins on April 15, 2008 at 06:14 AM PDT #

Very good tutorial

Posted by Amit on February 09, 2009 at 01:08 PM PST #

Awesome dude. I just ran your example and tried to implement it in my program. It ran successfully. Even the sun website and articles wasn't able to explain better. However I have one doubt regarding your example. Your are calculating the ciphertext length by // Calculate ciphertext size. Can you explain why are doing this? Instead of this one if i use cipherText.lenghth directly then I am getting "javax.crypto.ShortBufferException" warning. Please explain the below part in brief if you have time.

Posted by Amit Kumar Ruj on February 09, 2009 at 02:33 PM PST #

I also noticed that if you entering "Aryan" in your program then the program is not able to decrypt is again due to the below error.

ciphertext length: 16
javax.crypto.ShortBufferException

Please post the resolution for this.

Posted by guest on February 09, 2009 at 02:38 PM PST #

Amit,

Thanks for the compliments. Let me explain the algorithm a little further. Starting off, you have a plain text message that you want to encrypt. As you can see, data encryption can be considered low-level programming since you're dealing with data on a byte-by-byte basis instead of with Strings. So, I needed to calculate the size of the byte array that will hold the encrypted data. That's the reason why I have a section in the code to calculate the ciphertext size.

Thanks,

Bruce

Posted by Bruce Hopkins on February 10, 2009 at 09:50 PM PST #

Note, of you want to encrypt short words like "happy","joy", "love", or "Aryan" then reduce the blocksize from 16 to 8.

Let me know if that works for you.

Thanks!

Bruce

Posted by Bruce Hopkins on February 10, 2009 at 09:59 PM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Tips for developers who use Java technologies (Java SE, Java ME, JavaFX) for mobile and embedded devices.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today