Saturday, September 10, 2011

example of PKCS7Padding and ISO10126Padding

In my previous blog about How Padding Affects Block Cipher Encryption: PKCS7Padding vs ISO10126Padding, I explained why using the correct padding is important when using block cipher. Here is an example which demonstrate what happens, if we use the wrong padding for decryption.

The case1 demonstrates what I explained in previous blog, Here we encrypt password using PKCS7Padding and decrypt using ISO10126Padding and it works fine.


The case2 demonstrate the case where we encrypt password using ISO10126Padding and
decrpyt using PKCS7Padding and this fails with an error like:

javax.crypto.BadPaddingException: pad block corrupted decrypted password with PKCS7Padding: null

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeUtility;

public class EncryptionPaddingTest {

    private static final String KEY = "myowntestkey01234567890123456789";

    private static final String vector = "myowntestvector!";

    public static void main(String[] args) {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
 
        String password = "1234";
 
        //Case1: encrypt password using PKCS7Padding padding and decrypt using ISO10126Padding padding
        doEncryptionDecryption(password, "PKCS7Padding", "ISO10126Padding");

 
        //Case2: encrypt password using ISO10126Padding padding and decrypt using PKCS7Padding padding
        doEncryptionDecryption(password, "ISO10126Padding", "PKCS7Padding");

 
    }

    public static void doEncryptionDecryption(String input, String encryptionPadding, String decryptionPadding) {
 
        String encodedPassword = encryptUsingAES(input, encryptionPadding);
        System.out.println("encrypted password with " + encryptionPadding +": " + encodedPassword);
 
        //(2) decrypted password using encryptionPadding padding
        String decodedPassword1 = decryptUsingAES(encodedPassword, encryptionPadding);
        System.out.println("decrypted password with " +encryptionPadding + ": "+ decodedPassword1);
 
        //(3) decrypted password using decryptionPadding padding
        String decodedPassword2 = decryptUsingAES(encodedPassword, decryptionPadding);
        System.out.println("decrypted password with " +decryptionPadding + ": "+ decodedPassword2);
 
    }

    public static String encryptUsingAES(String input, String padding) {
        try {
            byte[] bytes = input.getBytes("UTF-8");
            Cipher cipher = Cipher.getInstance("Rijndael/CBC/"+padding);
            SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), "Rijndael");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(vector.getBytes()));
            byte[] encrypted = cipher.doFinal(bytes);
            byte[] base64Encoded = encodeBase64(encrypted);
            return new String(base64Encoded, "UTF-8");
            } catch (Exception e) {
            e.printStackTrace();
        }
 
        return null;
    }


    public static String decryptUsingAES(String input, String padding) {
        try {
            byte[] bytes = input.getBytes("UTF-8");
            byte[] base64Decoded = decodeBase64(bytes);
            Cipher cipher = Cipher.getInstance("Rijndael/CBC/"+padding);
            SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), "Rijndael");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(vector.getBytes()));
            byte[] decrypted = cipher.doFinal(base64Decoded);
     
            return new String(decrypted, "UTF-8");
            } catch (Exception e) {
            e.printStackTrace();
        }
 
        return null;
    }


    private static byte[] encodeBase64(byte[] b) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        OutputStream b64os = MimeUtility.encode(baos, "base64");
        b64os.write(b);
        b64os.close();
        return baos.toByteArray();
    }

    private static byte[] decodeBase64(byte[] b) throws Exception {
        ByteArrayInputStream bais = new ByteArrayInputStream(b);
        InputStream b64is = MimeUtility.decode(bais, "base64");
        byte[] tmp = new byte[b.length];
        int n = b64is.read(tmp);
        byte[] res = new byte[n];
        System.arraycopy(tmp, 0, res, 0, n);
        return res;
    }

}