0

I am retrieving a text password as input from a file and applying AES encryption over that and later on, decrypting that. When I did it for the first time, every 4 out of 5 times it was running correctly (encryption decryption successful) but 1 time, it was throwing BadPaddingException. Following is what I wrote :

//ABCD is class name
public static void enc(String fileName, String pwd) {
    try {
        Properties prop = new Properties();
        InputStream input = ABCD.class.getClassLoader().getResourceAsStream(fileName);
        prop.load(input);
        input.close();
        URL url = ABCD.class.getClassLoader().getResource(fileName);

        FileOutputStream outputStream = new FileOutputStream(url.getPath());
        KeyGenerator key = KeyGenerator.getInstance("AES");

        key.init(128);
        SecretKey aesKey = key.generateKey();
        String newkey = new  String(Base64.encode(aesKey.getEncoded()).getBytes("UTF-8"));

        Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
        byte[] clear = pwd.getBytes("UTF-8");
        byte[] cipher = aesCipher.doFinal(clear);
        String encPwd = new String(cipher);
        prop.setProperty("password", encPwd);
        prop.setProperty("secKey", newkey);
        prop.store(outputStream, null);
        outputStream.close();
    } catch (Exception e) {
        System.out.println(e);
    }
}

public static String dec(Properties prop, String fileName) {

    String decPwd = ABCD.map.get(fileName);
            try {
            String newkey = prop.getProperty("secKey");
            StringBuilder pwd;
            byte[] newkeybuff = Base64.decode(newkey.getBytes("UTF-8"));
            SecretKey key = new SecretKeySpec(newkeyuff, "AES");
            Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            aesCipher.init(Cipher.DECRYPT_MODE, key);
            pwd = new StringBuilder(prop.getProperty("password"));
            byte[] cipher = aesCipher.doFinal(pwd.toString().getBytes());
            decPwd = new String(cipher);
        } catch (Exception e) {
            System.out.println(e);
        }
        ABCD.map.put(fileName, decPwd);
    return decPwd;
}

I needed to fix this. Somewhere, I read that BadPaddingExcpetion occurs since of the operations done with String, in place of where actually byte should be used. Hence, I changed my code to the following :

public static void enc(String fileName, String pwd) {
    try {
        Properties prop = new Properties();
        InputStream input = ABCD.class.getClassLoader().getResourceAsStream(fileName);
        prop.load(input);
        input.close();
        URL url = ABCD.class.getClassLoader().getResource(fileName);

        FileOutputStream outputStream = new FileOutputStream(url.getPath());
        KeyGenerator key = KeyGenerator.getInstance("AES");

        key.init(128);
        SecretKey aesKey = key.generateKey();

        byte[] newkey=(Base64.encode(aesKey.getEncoded())).getBytes("UTF-8");

        Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");


        aesCipher.init(Cipher.ENCRYPT_MODE, aesKey,new IvParameterSpec(new byte[16]));
        byte[] clear = pwd.getBytes("UTF-8");
        byte[] cipher = aesCipher.doFinal(clear);

        prop.setProperty("password", Arrays.toString(cipher));
        prop.setProperty("secKey", Arrays.toString(newkey));

        prop.store(outputStream, null);
        outputStream.flush();
        outputStream.close();

    } catch (Exception e) {
    System.out.println(e);
}
}

public static String dec(Properties prop, String fileName) {

    String decPwd = ABCD.map.get(fileName);
            try {
            byte[] newkey=prop.getProperty("secKey").getBytes("UTF-8");
            byte[] pwd;


            byte[] newkeybuff = Base64.decode(newkey);
            SecretKeySpec key = new SecretKeySpec(newkeybuff, "AES");

            Cipher aesCipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
            aesCipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(new byte[16]));
            pwd = prop.getProperty("password").getBytes();

            byte[] cipher = aesCipher.doFinal(pwd);

            decPwd=new String(cipher);
            System.out.println("Decrypted pwd " + decPwd);

        } 
        catch (Exception e) {
    System.out.println(e);
}
        ABCD.map.put(fileName, decPwd);

    return decPwd;
}

Now, I am getting InvalidKeyException. This time, I read that the size of the key should be 16 bytes. But I don't know how to apply this. Need a fix for this!

Random Guy
  • 51
  • 3
  • 12
  • Your code is difficult to fix. I suggest you use some of the examples available in SO like http://stackoverflow.com/questions/15554296/simple-java-aes-encrypt-decrypt-example – pedrofb Feb 10 '17 at 07:05

2 Answers2

0

You should check your IV (Initialization Vector) which must be the same for encryption and decryption.

Tytou
  • 31
  • 2
0

A padding error usually means the decryption failed.

Check that the key is a full length (16, 24 or 32 bytes), the IV is full length (16-bytes). If the key or IV is to short it will be padded with "something"and that man not be consistent, there is no standard for such padding.

getBytes("UTF-8") may return different length of bytes depending on the characters used.

Using new IvParameterSpec(new byte[16]) for the IV is incorrect, the IV should be a random bytes. A usual method of handling the IV is to create a random IV on encryption and prepend it to the encrypted data, it does not need to be secret and by prepending it will be available for decryption.

zaph
  • 111,848
  • 21
  • 189
  • 228