Encrypt and decrypt with AES and Base64 encoding

Harshana picture Harshana · Oct 17, 2010 · Viewed 89.7k times · Source

I have following program for encrypting data.

import java.security.Key;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class Test {

    private static final String ALGORITHM = "AES";
    private static final byte[] keyValue = "ADBSJHJS12547896".getBytes();

    public static void main(String args[]) throws Exception {
        String encriptValue = encrypt("dude5");
        decrypt(encriptValue);

    }

    /**
     * @param args
     * @throws Exception
     */

    public static String encrypt(String valueToEnc) throws Exception {

        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.ENCRYPT_MODE, key);

        System.out.println("valueToEnc.getBytes().length "+valueToEnc.getBytes().length);
        byte[] encValue = c.doFinal(valueToEnc.getBytes());
        System.out.println("encValue length" + encValue.length);
        byte[] encryptedByteValue = new Base64().encode(encValue);
        String encryptedValue = encryptedByteValue.toString();
        System.out.println("encryptedValue " + encryptedValue);

        return encryptedValue;
    }

    public static String decrypt(String encryptedValue) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.DECRYPT_MODE, key);

        byte[] enctVal = c.doFinal(encryptedValue.getBytes());
        System.out.println("enctVal length " + enctVal.length);

        byte[] decordedValue = new Base64().decode(enctVal);

        return decordedValue.toString();
    }

    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, ALGORITHM);
        return key;
    }

}

Here I am getting the following out put with exception?

valueToEnc.getBytes().length 5
encValue length16
encryptedValue [B@aa9835
Exception in thread "main" javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)

Can some one explain me the cause? Why its only saying when decrypting that length should be 16. Doesn't it convert to 16 as like encrypting with the doFinal method.

And as the exception says "how to decrypting without padded cipher?"

Answer

Babu Srinivasan picture Babu Srinivasan · Apr 23, 2011

Your Order for encrypt: getBytes, encrypt, encode, toString
Your Order for decrypt(Wrong*): getBytes, decrypt, decode, toString

Two problems:

  1. As someone already mentioned you should reverse the order of operations for decryption. You are not doing that.
  2. encrypt gives you 16 bytes, encode 24 bytes, but toString gives 106 bytes. Something to do with invalid chars taking up additional space.

Note: Also, you don't need to call generateKey() twice.

Fix problem #1 by using the reverse order for decryption.
Correct order for decrypt: getBytes, decode, decrypt, toString

Fix problem #2 by replacing xxx.toString() with new String(xxx). Do this in both the encrypt and decrypt functions.

Your decrypt should look like this:

c.init(Cipher.DECRYPT_MODE, key)
val decodedValue = new Base64().decode(encryptedValue.getBytes())
val decryptedVal = c.doFinal(decodedValue)
return new String(decryptedVal)

This should give you back "dude5"