aspose file tools*
The moose likes Security and the fly likes Encryption and Decryption in J2ME Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » Security
Bookmark "Encryption and Decryption in J2ME" Watch "Encryption and Decryption in J2ME" New topic
Author

Encryption and Decryption in J2ME

Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

I am trying encryption and decryption of text using AES/CBC/PCKS5Padding but it throws IllegalblocksizeException



The Stack trace is

javax.crypto.IllegalBlockSizeException
at javax.crypto.Cipher.doFinal(), bci=36
- red.testEncrypt.decrypt(Ready.java:110)
- red.testEncrypt.encrypt(Ready.java:85)
- red.Ready.startApp(Ready.java:22)
at javax.microedition.midlet.MIDletTunnelImpl.callStartApp(), bci=1
at com.sun.midp.midlet.MIDletPeer.startApp(), bci=5
at com.sun.midp.midlet.MIDletStateHandler.startSuite(), bci=261
at com.sun.midp.main.AbstractMIDletSuiteLoader.startSuite(), bci=38
at com.sun.midp.main.CldcMIDletSuiteLoader.startSuite(), bci=5
at com.sun.midp.main.AbstractMIDletSuiteLoader.runMIDletSuite(), bci=144
at com.sun.midp.main.AppIsolateMIDletSuiteLoader.main(), bci=26


I am breaking my head to find out what went wrong in this for 2 days. Please help me


"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
--- Martin Fowler
Maneesh Godbole
Saloon Keeper

Joined: Jul 26, 2007
Posts: 10360
    
    8

Not really a JME question. Moving...


[How to ask questions] [Donate a pint, save a life!] [Onff-turn it on!]
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Thanks Maneesh and sorry for posting in wrong forum

I have another doubt, I encrypt the string and encode it but when I decode it I don't get the encrypted string I get something similar to encoded bytes

Why is it so?
Richard Tookey
Ranch Hand

Joined: Aug 27, 2012
Posts: 1053
    
  10

Your code

means that your ciphertext length is always 200 bytes so you are always trying to decrypt 200 bytes! You just need

Similarly, in your decrypt() method you only need

There are other not so critical things wrong with your code but I will let you deal with those.

P.S. Please please please don't provide comments that are actually wrong. In the first bit of your code I quoted the comment "Decrypt the data " should actually be "Encrypt the data "!
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Richard,

Thanks for you reply. But the cipher.doFinal() method in J2ME doesn't accept one argument. The syntax is doFinal(byte[](input),offset,length,byte[](output),offset). So I cannot do the way you have suggested. The byte[] output is just the Base 64 decoded of the actual byte[] passed to the decrypt method. The byte[] red is actually the array containing the decrypted code. I need to initialize it but I won't know how long the text will be. Also I don't think there is a possible way to initialize a dynamic array. So how can I initialize the byte[] red? And as I previously mentioned above when I base 64 decode the encoded bytes I don't get the same result.


I tried changing byte[] red = new byte[200] to byte[] red = null but now it throws java.lang.IllegalArgumentException: output out of bounds
Richard Tookey
Ranch Hand

Joined: Aug 27, 2012
Posts: 1053
    
  10

The doFinal() method you are using returns, to quote the Javadoc, "the number of bytes stored in output" so you then have to use when generating the Base64 output. You can also use the Cipher method getOutputSize(int inputLen) when creating the 'red' array. Please read the Javadoc, it will save you a load of time.
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Richard,

I have read the javadoc but the problem is JME doesn't support getOutputsize method. Only getClass and getIV methods are working the Base64 encoder and decoder works fine. I was wrong previously and I can't get the size from doFinal method, since the error occurs in the same line.
Richard Tookey
Ranch Hand

Joined: Aug 27, 2012
Posts: 1053
    
  10

Partheban Udayakumar wrote:Richard,

I have read the javadoc but the problem is JME doesn't support getOutputsize method. Only getClass and getIV methods are working the Base64 encoder and decoder works fine. I was wrong previously and I can't get the size from doFinal method, since the error occurs in the same line.


OK but the doFinal() method must return the length of the resulting ciperhtext and an upper bound on the size of your 'red' byte array is the cleartext length + 16 ! This will allow you to avoid the exception and to extract the ciphertext from the 'red' array!

P.S. Can you point me at the Javadoc for the Cipher class you are using because it seems overly restrictive.
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Richard,

I dont think there is a unique javadoc for this, its basically the normal javax.crypto.Cipher. But when I implement it in JME its becomes restrictive.

I tried the following



I used the x in the decrypt method as



still I get the same error.

P.S. I have just shown the corrections i have made rest remains same as in the code shown above.
Richard Tookey
Ranch Hand

Joined: Aug 27, 2012
Posts: 1053
    
  10

I'm not going to try to construct your latest code from the fragments. You should post the latest version preferably as an SSCCE and post the full exception trace .



Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Richard,

Sorry. I have made some more changes too.



javax.crypto.IllegalBlockSizeException
at javax.crypto.Cipher.doFinal(), bci=36
- red.testEncrypt.decrypt(Ready.java:116)
- red.testEncrypt.encrypt(Ready.java:88)
- red.Ready.startApp(Ready.java:23)
at javax.microedition.midlet.MIDletTunnelImpl.callStartApp(), bci=1
at com.sun.midp.midlet.MIDletPeer.startApp(), bci=5
at com.sun.midp.midlet.MIDletStateHandler.startSuite(), bci=261
at com.sun.midp.main.AbstractMIDletSuiteLoader.startSuite(), bci=38
at com.sun.midp.main.CldcMIDletSuiteLoader.startSuite(), bci=5
at com.sun.midp.main.AbstractMIDletSuiteLoader.runMIDletSuite(), bci=144
at com.sun.midp.main.AppIsolateMIDletSuiteLoader.main(), bci=26
Richard Tookey
Ranch Hand

Joined: Aug 27, 2012
Posts: 1053
    
  10

Let us look first at your encrypt() method.

1) Not serious but silly - you do not need to pass the 'x' value to the decryp() method since it should be reflected in the length of the ciphertext.
2) Not serious - but you should not use a magic constant 20 when working out the upper bound for the cipehrtext length. You should use cipher.getBlockSize()
3) Serious - for some reason when using the doFinal() method write the output starting at index 1 instead of index 0. This means that when you decrypt you ignore the last byte of the ciphertext !
4) Serious - after you have done the doFinal() you need to extract the first 'x' bytes from 'encrypted' . The easiest way to do this is to use Arrays.copyOf() i.e. encrypted = Arrays.copyOf(encrypted, x); If Array.copyof() is not available in you j2me then you will have to code the equivalent. You don't say which Base64 encoder you are using but if the Base64 encoder method allows you to specify the length to encode then you don't actually need create a copy of the ciphertext array.
5) Not serious - it is a waste of time creating a string from the 'encrypted' data as it has no meaning and will normally contain non-printable characters.
6) Potentially serious - if anything goes wrong with the encryption and an exception is thrown you carry on regardless. Why since it means that the encryption has probably not taken place and you have a system error. Just throw the exception or wrap it in one of your own exceptions and throw that but don'e just continue.

Now the decrypt() method. Points (1) and (6) above obviously applies to decryp method.
a) Very serious - once again you ignore the length returned by the doFinal() method. Why? It tells you the length of the recovered clear text.
b)Serious - an upper bound for the length of the decrypted data is not 'x' but is the length of the Base64 decoded ciphertext.
c) Very serious - once again you are writing the output starting at location 1 instead of location 0. See note (3) above.
d) Very serious - when creating the String of the recovered cleartext you need to take into account length returned by the doFinal() method. Note that there is a String constructor that can use the length.

General - when converting a String to bytes or bytes to a String you should not use the platform default character encoding since the person doing the decryption may not have the same default character encoding as the person doing the encryption. I always specify utf-8 since it will guarantee to handle pretty much all input.

When I implement the above points your code works correctly.
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Richard,

Oh My God. First, I would like to thank you for taking so much time to explain things to me. I have followed what ever you have said and I got the results but I still have some doubts. I will ask in the same fashion in which you have suggested things to me.

encrypt() method:

1) You are right I didn't need to do that.

2) cipher.getBlockSize() isn't working in JME

3) Ya I used 1 instead of 0. I recognized it later now I have changed it.

4) (i) The doFinal() method stores a byte[] with encrypted data right? How do i initialize the byte[] ? If I initialize it with null, it throws Null Pointer Exception.

(ii) The doFinal() method actually encrypts and then pads the missing bits right? so if i extract with 'x' size again all the bytes are copied right?

(iii) I use the Base64 encoder and decoder of Bouncy Castle. Arrays.copyof() works from Bouncy Castle.

5) Ok. Now I get that.

6) I think I have caught exception using try catch block but with general exception. You want me to catch individual exception right?

decrypt() method:

a) OK. I will handle the integer returned.

b) When the length of the encrypted text dilemma is cleared, I think I can make a more clear code.

c) Ya. I have changed them.

d) Ya I got your point and I implemented it.

Can I use the same program for tripleDES encryption?

P.S : I would like to have a clear and correct conversation so I used this method.
Richard Tookey
Ranch Hand

Joined: Aug 27, 2012
Posts: 1053
    
  10

Partheban Udayakumar wrote:
Oh My God. First, I would like to thank you for taking so much time to explain things to me. I have followed what ever you have said and I got the results but I still have some doubts. I will ask in the same fashion in which you have suggested things to me.

encrypt() method:

1) You are right I didn't need to do that.

2) cipher.getBlockSize() isn't working in JME

How silly is j2me .They do their best to make writing good code difficult. Define a static int constant with value 16 and use that. Maybe give it the name BLOCK_SIZE !

3) Ya I used 1 instead of 0. I recognized it later now I have changed it.

4) (i) The doFinal() method stores a byte[] with encrypted data right? How do i initialize the byte[] ? If I initialize it with null, it throws Null Pointer Exception.

I'm not sure I understand you. You do just as you have done! You just do a "new byte[some length]".

(ii) The doFinal() method actually encrypts and then pads the missing bits right?

Nearly - on encrypt it pads to a multiple of the block size and then encrypts. This is what the PKCS5Padding indicates should happen. On decrypt it first decrypts and then removes the padding introduced in the encryption.

so if i extract with 'x' size again all the bytes are copied right?

I don't really understand what you mean here. On encryption, N bytes of cleartext generates 'x' bytes of cipher text and on decryption 'x' bytes of ciphertext generates N bytes of cleartext.

Encryption is a layered system; the process is

cleartext is padded and then encrypted to ciphertext and then (optionally) Base64 or Hex encoded.

To decrypt one just reverses the steps. One removes any encoding, decrypts and then removes the padding.


(iii) I use the Base64 encoder and decoder of Bouncy Castle. Arrays.copyof() works from Bouncy Castle.

I would be surprised if j2me did not have AES by default so you might do better with Apache Commons Codec Base64 since you don't need most of the BC library.

5) Ok. Now I get that.

6) I think I have caught exception using try catch block but with general exception. You want me to catch individual exception right?

Not really. If one can sensibly handle an exception then one should do so but in this case if you get an exception it must be a system error which your code can do nothing about so don't try to handle it but just pass it back to the calling process. In order to isolate the calling process from the detail of the encryption process it is normally better to actually wrap the exception in some home grown exception or as I do these days just wrap it in an Error. For example



decrypt() method:

a) OK. I will handle the integer returned.

b) When the length of the encrypted text dilemma is cleared, I think I can make a more clear code.

c) Ya. I have changed them.

d) Ya I got your point and I implemented it.

Can I use the same program for tripleDES encryption?

With a few changes yes. The block size for TripleDes is only 8 bytes so the IV can only be 8 bytes. Also the TrippleDES key is 3*56 bits packaged as 24 bytes.

But why would you want to use TripleDES? TripleDES is very slow compared to AES and AES is now the industry standard and replaced TripleDES some while ago.

P.S : I would like to have a clear and correct conversation so I used this method.


One last point. I don't really like to see a key generated from a password in the way that you have done. If you have to use a password then use one of the more standard approaches for converting a password to a key.


Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Richard,

Define a static int constant with value 16 and use that. Maybe give it the name BLOCK_SIZE !


If I declare byte[] red = new byte[16], short buffer exception is thrown.

I don't really understand what you mean here. On encryption, N bytes of clear text generates 'x' bytes of cipher text and on decryption 'x' bytes of cipher text generates N bytes of clear text.


The integer x stores the no of bytes which are encrypted and padded right? So if I extract x bytes from the string then same will result right?

I would be surprised if j2me did not have AES by default so you might do better with Apache Commons Codec Base64 since you don't need most of the BC library.


I use Bouncy Castle for Big Integer and Secure Random to do RSA encryption. Now that is a dead end too. Obfuscation ain't working. I got to open a new thread for that next but let me finish this one first.

One last point. I don't really like to see a key generated from a password in the way that you have done. If you have to use a password then use one of the more standard approaches for converting a password to a key.


Actually we are looking for Random key generation. This is just a test code.
Richard Tookey
Ranch Hand

Joined: Aug 27, 2012
Posts: 1053
    
  10

Partheban Udayakumar wrote:Richard,

Define a static int constant with value 16 and use that. Maybe give it the name BLOCK_SIZE !


If I declare byte[] red = new byte[16], short buffer exception is thrown.

You are missing the point ! In your code line

you have the magic number 20! Anybody trying to read your code will say "what the hell is that magic number?" .

You need to make the 'encrypted' array at least big enough to hold your ciphertext so you need to know an upper bound for the length of the ciphertext. One simple upper bound it the length of the cleartext + the blocksize . So I was suggesting you use define a static constant

and then define your 'encrypted' array as

now the reader of you code won't be asking "what the hell is the magic number 20".

For you simple single doFinal() it is possible to calculate the exact length of the ciphertext. I didn't mention it earlier since it was much more important to deal with the serious problems. For PKCS5 padding

clphertext.length = ((cleartext.length + BLOCK_SIZE + 1) / BLOCK_SIZE ) * BLOCK_SIZE

I will leave you to do the research on this.


I don't really understand what you mean here. On encryption, N bytes of clear text generates 'x' bytes of cipher text and on decryption 'x' bytes of cipher text generates N bytes of clear text.


The integer x stores the no of bytes which are encrypted and padded right? So if I extract x bytes from the string then same will result right?


'x' bytes from the byte array (not the string!).


I would be surprised if j2me did not have AES by default so you might do better with Apache Commons Codec Base64 since you don't need most of the BC library.


I use Bouncy Castle for Big Integer and Secure Random to do RSA encryption. Now that is a dead end too. Obfuscation ain't working. I got to open a new thread for that next but let me finish this one first.

One last point. I don't really like to see a key generated from a password in the way that you have done. If you have to use a password then use one of the more standard approaches for converting a password to a key.


Actually we are looking for Random key generation. This is just a test code.


Random key generation is possible but having generated a random key and used it in some encryption how are you going to pass that random key to the person who needs to do the decryption? This is the classic 'key distribution' problem !

Why is RSA dead to you?

What problem are you trying to solve and how do you think 'obfuscation' might help?
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Richard,

Thank you once again.

I will research on the formula you have provided. RSA is not dead, I am actually trying to use it. Big Integer and Secure Random classes don't exist in JME. So I googled how to obtain them and the only result I found was to obfuscate the jar file. I am not even sure that I know about obfuscation. I tried all the suggested activities for obfuscation like adding some ant code to build.xml file. Using obfuscator provided in Netbeans. Nothing solves it. I think I may be doing something wrong but I don't have a clear idea about obfuscation.

And as for the keys, if I use encryption say for encrypting a message sent via my messaging application in JME, can we use the same key for multiple clients who have my messaging application?
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41818
    
  62
Partheban Udayakumar wrote:Big Integer and Secure Random classes don't exist in JME. So I googled how to obtain them and the only result I found was to obfuscate the jar file.

Yes, I think you fundamentally misunderstood something about that. Obfuscation has nothing to do with those classes.


Ping & DNS - my free Android networking tools app
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Ulf,

But in all the posts I saw, they said using obfuscator solved their program. But it didn't solve mine. I saw one similar post here. I didn't understand properly what was said but I tried renaming the class files as well as the folders but didn't work.
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41818
    
  62
I stand corrected. It appears that obfuscation does (or used to) help with some security-relatived JME problem. But I don't think that problem has anything to do with the issues being discussed here in this topic.
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Ulf,

No problem. I need to generate random keys in J2ME, for that I need Secure Random class, so we started talking about obfuscation here.
Richard Tookey
Ranch Hand

Joined: Aug 27, 2012
Posts: 1053
    
  10

The 149 distribution of BouncyCastle has a J2ME section that includes implementations of SecureRandom and BigInteger. I have never used them and have no J2ME device to try them on so I don't know how good they are but it must be worth investigating.
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Richard,

For JME, its lcrypto-j2me-149. It is the 149 distribution. But it doesn't work.

I have one more doubt about I V here. How can we generate I V which isn't related to our key? i want that to be random too.
Richard Tookey
Ranch Hand

Joined: Aug 27, 2012
Posts: 1053
    
  10

Partheban Udayakumar wrote:
For JME, its lcrypto-j2me-149. It is the 149 distribution. But it doesn't work.

Seems unlikely. In what way does it not work?

I have one more doubt about I V here. How can we generate I V which isn't related to our key? i want that to be random too.


You generate a random IV in the same way as you generate a random key! There is a difference in the secrecy requirement. Your key must be kept very very secret and only revealed to the people who must do the decryption. The IV does not have to be kept secret and can be shipped with the ciphertext. One common approach is to prepend the IV to the ciphertext. For security reasons it is best if the IV is different for every message even if the key does not change.
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Richard,

I obfuscated jar file using pro guard obfuscator provided in netbeans. I downloaded pro guard and obfuscated the jar file, still it shows Noclassdeffound error for Secure Random.

You generate a random IV in the same way as you generate a random key! There is a difference in the secrecy requirement. Your key must be kept very very secret and only revealed to the people who must do the decryption. The IV does not have to be kept secret and can be shipped with the ciphertext. One common approach is to prepend the IV to the ciphertext. For security reasons it is best if the IV is different for every message even if the key does not change.


Ok. I have one more doubt, I generated random keys and iv in a servlet and passed it to method. I get the keys and iv fine but the cipher .init method throws InvalidAlgorithmParameter exception now.



The print statements ,


gives
key: javax.crypto.spec.SecretKeySpec@1c950eef
IV: javax.crypto.spec.IvParameterSpec@1d3615ce


and the stack trace is



java.security.InvalidAlgorithmParameterException
at javax.crypto.Cipher.init(), bci=199
- red.testEncrypt.encrypt(Ready.java:97)
- red.Ready.connect(Ready.java:52)
- red.Ready.startApp(Ready.java:31)
at javax.microedition.midlet.MIDletTunnelImpl.callStartApp(), bci=1
at com.sun.midp.midlet.MIDletPeer.startApp(), bci=5
at com.sun.midp.midlet.MIDletStateHandler.startSuite(), bci=261
at com.sun.midp.main.AbstractMIDletSuiteLoader.startSuite(), bci=38
at com.sun.midp.main.CldcMIDletSuiteLoader.startSuite(), bci=5
at com.sun.midp.main.AbstractMIDletSuiteLoader.runMIDletSuite(), bci=144
at com.sun.midp.main.AppIsolateMIDletSuiteLoader.main(), bci=26
Richard Tookey
Ranch Hand

Joined: Aug 27, 2012
Posts: 1053
    
  10

Partheban Udayakumar wrote:Richard,

I obfuscated jar file using pro guard obfuscator provided in netbeans. I downloaded pro guard and obfuscated the jar file, still it shows Noclassdeffound error for Secure Random.

You have lost me! What are you obfuscating and why? Obfuscation is a way to make it difficult to recover Java source files from class file so there is no point in obfuscating the BC jar since the source is freely available!



You generate a random IV in the same way as you generate a random key! There is a difference in the secrecy requirement. Your key must be kept very very secret and only revealed to the people who must do the decryption. The IV does not have to be kept secret and can be shipped with the ciphertext. One common approach is to prepend the IV to the ciphertext. For security reasons it is best if the IV is different for every message even if the key does not change.


Ok. I have one more doubt, I generated random keys and iv in a servlet and passed it to method. I get the keys and iv fine but the cipher .init method throws InvalidAlgorithmParameter exception now.

Your IV array is not 16 bytes long. I should not need to tell you this since you could easily have deduced this from the exception and stack trace!

Your print statements are useless for debugging since these toString() method do not in any way reflect the content of the object. You should Hex encode the content of the internal arrays and print that.

In my previous posts I explained that one should not use magic numbers since they make the code difficult to follow. I explained that it is better to use a static constant such as BLOCK_SIZE which you have obfuscated to the ridiculous name of 'xd' ! And why are you still using that silly variable name 'x'?

Before posting again to this thread or anywhere else please please please make sure you make it easy for the reader by using meaningful variable names and follow the Java coding standards.
Partheban Udayakumar
Ranch Hand

Joined: Jul 04, 2013
Posts: 247

Richard,

Thanks. I figured it out after I posted here. Sorry. I am now trying RSA encryption. I have few doubts. I will ask those in a separate thread.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Encryption and Decryption in J2ME