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;
    }

}





Sunday, August 28, 2011

Spring: Unit Test, Reload Context After Each Test Or Test Class

Recently I came across a situation while doing some unit test using spring SpringJUnit4ClassRunner where after each test, the spring application context is no longer good for it to be reused in the next test. After some digging, I found out that there is this DirtiesContext annotation which one can use in the unit test to force spring to reload context.

It has two options:

(1) One is reload context after each test.
(2) Second is to reload context after all the tests of a class.

This is very useful and it also means that when running unit test using spring, by default the application context is loaded once and used to run all the tests.

Promote your blog