Reputation: 145
eg. here javax.crypto.BadPaddingException: Given final block not properly padded error while decryption or here Given final block not properly padded
I want to encrypt and then decrypt Strings. Read many topics about "Given final block not properly padded" exception, but non of these solutions worked.
My Class:
package aes;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.swing.JOptionPane;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class EncryptionExample {
private static SecretKeySpec key;
private static IvParameterSpec ivSpec;
private static Cipher cipher;
private static byte[] keyBytes;
private static byte[] ivBytes;
private static int enc_len;
public static void generateKey() throws Exception
{
String complex = new String ("9#82jdkeo!2DcASg");
keyBytes = complex.getBytes();
key = new SecretKeySpec(keyBytes, "AES");
complex = new String("@o9kjbhylK8(kJh7"); //just some randoms, for now
ivBytes = complex.getBytes();
ivSpec = new IvParameterSpec(ivBytes);
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
}
public static String encrypt(String packet) throws Exception
{
byte[] packet2 = packet.getBytes();
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encrypted = new byte[cipher.getOutputSize(packet2.length)];
enc_len = cipher.update(packet2, 0, packet2.length, encrypted, 0);
enc_len += cipher.doFinal(encrypted, enc_len);
return packet = new String(encrypted);
}
public static String decrypt(String packet) throws Exception
{
byte[] packet2 = packet.getBytes();
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = new byte[cipher.getOutputSize(enc_len)];
int dec_len = cipher.update(packet2, 0, enc_len, decrypted, 0);
HERE EXCEPTION>>>>> dec_len += cipher.doFinal(decrypted, dec_len); <<<<<<<<<
return packet = new String(decrypted);
}
// and display the results
public static void main (String[] args) throws Exception
{
// get the text to encrypt
generateKey();
String inputText = JOptionPane.showInputDialog("Input your message: ");
String encrypted = encrypt(inputText);
String decrypted = decrypt(encrypted);
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
"Encrypted: " + new String(encrypted) + "\n"
+ "Decrypted: : " + new String(decrypted));
.exit(0);
}
}
The thing is, when I decrypt strings (about 4/10 of shots), I get that exception:
Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:479)
at javax.crypto.Cipher.doFinal(Cipher.java:2068)
at aes.EncryptionExample.deszyfrujBez(EncryptionExample.java:HERE tag)
at aes.EncryptionExample.main(EncryptionExample.java:Main starting)
Does anybody know what to change here (key? *.doFinal() method?) to make it work?
@ for those curious - methods have to be static, as this is a part of something bigger ;)
Upvotes: 1
Views: 18560
Reputation: 8467
When you use byte[] packet2 = packet.getBytes()
you are converting the string based on the default encoding, which could be UTF-8, for example. That's fine. But then you convert the ciphertext back to a string like this: return packet = new String(encrypted)
and this can get you into trouble if this does not round-trip to the same byte array later in decrypt() with another byte[] packet2 = packet.getBytes()
.
Try this instead: return packet = new String(encrypted, "ISO-8859-1")
, and byte[] packet2 = packet.getBytes("ISO-8859-1")
-- it's not what I would prefer, but it should round-trip the byte arrays.
Upvotes: 4
Reputation: 43738
The result of encryption is binary data. In most cases it cannot be interpreted as a valid string encoding. So the call to new String(encrypted)
will most likely distort the encrypted bytes and after doing packet.getBytes()
you end up with a byte array with different content.
The decryption now fails because the cypher text has been changed. The padding bytes are not correctly recovered and cannot be removed.
To fix that, don't convert the cypher text to a string, keep the byte array.
Upvotes: 0