0

I need to send some crypted data over REST. My crypter / decrypter class is as follows:

public class AesCrypter {
    static String IV = "AAAAAAAAAAAAAAAA";
    static String aesKey = "0123456789abcdef";

    public static byte[] encrypt(String unecryptedText) throws Exception {
        Cipher encrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
        SecretKeySpec key = new SecretKeySpec(aesKey.getBytes("UTF-8"), "AES");
        encrypt.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
        return encrypt.doFinal(unecryptedText.getBytes("UTF-8"));
    }

    public static String decrypt(String cryptedText) throws Exception{
        byte[] bytes = cryptedText.getBytes(StandardCharsets.UTF_8);
        Cipher decrypt = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
        SecretKeySpec key = new SecretKeySpec(aesKey.getBytes("UTF-8"), "AES");
        decrypt.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
        return new String(decrypt.doFinal(bytes),"UTF-8"); // this line
    }
}

But I'm getting a javax.crypto.BadPaddingException: Given final block not properly padded on the decrypt method, console points out error to be on the line I commented with // this line.

What am I missing out here?

gtludwig
  • 5,411
  • 10
  • 64
  • 90
  • 2
    How do you transform the byte array returned by encrypt() to a String to pass to decrypt()? decrypt() should take a byte array as argument. It makes no sense to transform random bytes to a String using UTF8, because not all byte sequences represent a valid UTF8 string. So it's a lossy transformation. use Base64 encoding if you need a String. – JB Nizet Jun 18 '16 at 15:51
  • In short, I should replace all references of `UTF-8` to `Base64`, right? – gtludwig Jun 18 '16 at 16:00
  • 2
    No. Transforming a String to a byte array using UTF8 is fine (as you're doing for the key and the IV and the text). What is wrong is the code you haven't shown, and which most probably does: `String encryptedText = new String(encryptedBytes, "UTF8")`. That's where you should use Base64. But Base64 is not a charset as UTF8 is. See http://docs.oracle.com/javase/8/docs/api/java/util/Base64.html. Of course, if you use base64 encoding to go from encrypted byte[] to encrypted string, you will also need to use base64 decoding to go from encrypted string to encrypted byte[]. – JB Nizet Jun 18 '16 at 16:04
  • 1
    The IV must be unpredictable (read: random). Don't use a static IV, because that makes the cipher deterministic and therefore not semantically secure. An attacker who observes ciphertexts can determine when the same message prefix was sent before. The IV is not secret, so you can send it along with the ciphertext. Usually, it is simply prepended to the ciphertext and sliced off before decryption. – Artjom B. Jun 20 '16 at 10:01

1 Answers1

1

Actual Scenerio of PKCS5-Padding causes javax.crypto.BadPaddingException

If you try to decrypt PKCS5-padded data with the wrong key, and then unpad it (which is done by the Cipher class automatically), you most likely will get the BadPaddingException (with probably of slightly less than 255/256, around 99.61%), because the padding has a special structure which is validated during unpad and very few keys would produce a valid padding.

So, if you get this exception, catch it and treat it as "wrong key".

This also can happen when you provide a wrong password, which then is used to get the key from a keystore, or which is converted into a key using a key generation function.

Of course, bad padding can also happen if your data is corrupted in transport.

So you can follow Base64:

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


 public static String base64Encode(String token) {
    byte[] encodedBytes = Base64.encode(token.getBytes());
    return new String(encodedBytes, Charset.forName("UTF-8"));
}


public static String base64Decode(String token) {
    byte[] decodedBytes = Base64.decode(token.getBytes());
    return new String(decodedBytes, Charset.forName("UTF-8"));
}

Resource Link:

  1. Base64 Encoding in Java
Community
  • 1
  • 1
SkyWalker
  • 28,384
  • 14
  • 74
  • 132