1

Am a new to J2ME. Currently am told to do a project which require AES encryption. I got a code snippet after some search on Google. The code does encrypt but when when trying to decrypt am getting error "Invalidkeyexception"

The code is

package com.cellapp.voda.vault.others;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;


public class Codec {

    private Cipher cipher = null;
    private boolean operative = true;

    public Codec() {

        try {
            cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        } catch (NoSuchAlgorithmException e) {
            // This should not happen since we know the target platform
            // but we set the operative flag to false just in case
            operative = false;
        } catch (NoSuchPaddingException e) {
            // This should not happen since we know the target platform
            // but we set the operative flag to false just in case
            operative = false;
        }
    }


    public void encrypt(byte[] keyBits, byte[] plaintext)
            throws InvalidKeySpecException, InvalidKeyException,
            IllegalStateException, ShortBufferException,
            IllegalBlockSizeException, BadPaddingException,
            InvalidAlgorithmParameterException {
            byte[] cipherText = null;
        if (operative) {
           try{
                // Initialize the key from  the password
            Key key = new SecretKeySpec(keyBits, 0, keyBits.length, "AES");
            // add 2 bytes to encode the length of the plaintext
            // as a short value
            byte[] plaintextAndLength = new byte[plaintext.length + 2];
            plaintextAndLength[0] = (byte) (0xff & (plaintext.length >> 8));
            plaintextAndLength[1] = (byte) (0xff & plaintext.length);
            // build the new plaintext
            System.arraycopy(plaintext,
                    0,
                    plaintextAndLength,
                    2,
                    plaintext.length);

            // calculate the size of the ciperthext considering
            // the padding
            int blocksize = 16;
            int ciphertextLength = 0;
            int remainder = plaintextAndLength.length % blocksize;
            if (remainder == 0) {
                ciphertextLength = plaintextAndLength.length;
            } else {
                ciphertextLength = plaintextAndLength.length - remainder
                        + blocksize;
            }
            cipherText = new byte[ciphertextLength];

            // reinitialize the cipher in encryption mode with the given key
            cipher.init(Cipher.ENCRYPT_MODE, key);
            // do the encryption
            cipher.doFinal(plaintextAndLength,
                    0,
                    plaintextAndLength.length,
                    cipherText,
                    0);
           }
           catch(Exception e)
           {
               System.out.println("TT " + cipherText);
           }


        } else {
            throw new IllegalStateException("Codec not initialized");
        }
    }

    public void decrypt(byte[] keyBits, byte[] cipherText)
            throws InvalidKeySpecException, InvalidKeyException,
            IllegalStateException, ShortBufferException,
            IllegalBlockSizeException, BadPaddingException,
            InvalidAlgorithmParameterException {
        if (operative) {
            // create a key from the keyBits
            Key key = new SecretKeySpec(keyBits, 0, keyBits.length, "AES");

            // Initialize the cipher in decrypt mode
            cipher.init(Cipher.DECRYPT_MODE, key);

            byte[] decrypted = new byte[cipherText.length];
            // Decrypt the cipher text
            cipher.doFinal(cipherText, 0, cipherText.length, decrypted, 0);
            // Calculate the length of the plaintext
            int plainTextLength = (decrypted[0] << 8)
                    | (decrypted[1] & 0xff);
            byte[] finalText = new byte[plainTextLength];
            // Decode the final text
            System.arraycopy(decrypted, 2, finalText, 0, plainTextLength);

            System.out.println("fina;  text " + finalText);
        } else {
            throw new IllegalStateException("Codec not initialized");
        }
    }

    // Displays ecrypted data in hex
    public String byteToHex(byte[] data) {
        StringBuffer hexString = new StringBuffer();
        String hexCodes = "0123456789ABCDEF";

        for (int i = 0; i < data.length; i++) {
            hexString.append(hexCodes.charAt((data[i] >> 4) & 0x0f));
            hexString.append(hexCodes.charAt(data[i] & 0x0f));
            if (i < data.length - 1) {
                hexString.append(":");
            }
            if (((i + 1) % 8) == 0) {
                hexString.append("\n");
            }
        }
        return hexString.toString();
    }
}
4
  • 1
    Please add a main() method to your code so that we can run it and demonstrate the problem. Commented Jul 31, 2013 at 11:15
  • Please have your managers read this: blogs.msdn.com/b/ericlippert/archive/2011/09/27/… Also make sure they understand that someone who is not highly skilled in security and cryptography will not be able to produce a secure program out of cryptographic primitives like AES. Commented Jul 31, 2013 at 11:17
  • You are using ECB mode. DON'T DO THAT! It is insecure. Use CBC or CTR mode instead. Commented Jul 31, 2013 at 11:55
  • rossum okay i will check with tht Commented Jul 31, 2013 at 12:05

1 Answer 1

1

The code you've listed is bad for a number of reasons (using ECB, Cipher is not thread safe, not doing padding correctly, etc.), I highly suggest that you do not use it.

I had this lying around, you should probably use it instead.

public static void main(String[] args) throws DecoderException, InvalidKeyException,
        NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException,
        IllegalBlockSizeException, BadPaddingException {
    //Hex encoding/decoding done with Apache Codec library.
    //key MUST BE 16, 24 or 32 random bytes.
    //Do not reuse this key! Create your own.
    byte[] key = Hex.decodeHex("a3134dfd51c30f6e25343d861320668e".toCharArray());
    String text = "This is some test text.";

    byte[] encrypted = encrypt(key, text.getBytes());
    byte[] decrypted = decrypt(key, encrypted);

    System.out.println("Text: " + text);
    System.out.println("Encrypted: " + Hex.encodeHexString(encrypted));
    System.out.println("Decrypted: " + new String(decrypted));
}

public static byte[] encrypt(byte[] key, byte[] unencrypted) throws NoSuchAlgorithmException,
        NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException,
        IllegalBlockSizeException, BadPaddingException{
    //Create an initialization vector
    //SecureRandom is not available on J2ME, so we use Bouncy Castle's DigestRandomGenerator instead.
    DigestRandomGenerator rnd = new DigestRandomGenerator(new SHA1Digest());
    //SecureRandom rnd = new SecureRandom();
    byte[] iv = new byte[16];
    rnd.nextBytes(iv);
    IvParameterSpec ivSpec = new IvParameterSpec(iv);

    //Set up the cipher and encrypt
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), ivSpec);
    byte[] encrypted = cipher.doFinal(unencrypted);

    //Append the encrypted text to the IV
    byte[] output = new byte[iv.length + encrypted.length];
    System.arraycopy(iv, 0, output, 0, iv.length);
    System.arraycopy(encrypted, 0, output, iv.length, encrypted.length);
    return output;
}

public static byte[] decrypt(byte[] key, byte[] encrypted) throws NoSuchAlgorithmException,
        NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException,
        IllegalBlockSizeException, BadPaddingException{
    //Separate the IV and encrypted text
    byte[] iv = new byte[16];
    byte[] encryptedText = new byte[encrypted.length - iv.length];
    System.arraycopy(encrypted, 0, iv, 0, iv.length);
    System.arraycopy(encrypted, iv.length, encryptedText, 0, encryptedText.length);

    //Decrypt the encrypted text
    IvParameterSpec ivSpec = new IvParameterSpec(iv);
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), ivSpec);
    byte[] decrypted = cipher.doFinal(encryptedText);

    return decrypted;
}
Sign up to request clarification or add additional context in comments.

6 Comments

r u sure about SecureRandom.. when i tried to implement the above code.. I couldnt import SecureRandom... am working on j2me
Ah, sorry about that. Ideally you should use an encryption provider like BouncyCastle to provide this functionality. Replacing SecureRandom with DigestRandomGenerator rnd = new DigestRandomGenerator(new SHA1Digest()). For testing, you can just use Java's Random class instead. Though, I really encourage you to use Bouncy Castle for this when you actually deploy your code.
am getting an error "invalidkeyexception" do u ve ny idea why it comes...? am getting error at here cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), ivSpec);
@suja How long is the key you are using? It should be 16 bytes.
Well? What size is your key? If it's stored as hex, are you sure you're decoding it before you try to use it? ntoskrnl is correct, the issue is almost certainly that your is the wrong length.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.