Reputation: 69
I have little problem. When I try to encrypt text and then decrypt this text I get an error:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
Here is my code:
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
*
* @author Grzesiek
*/
public class SymmethricCipherCBC {
/* Klucz: */
private byte[] keyBytes = new byte[] {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
0x00,0x01,0x02,0x03,0x04,0x05
};
/* Wektor inicjalizacyjny: */
private byte[] ivBytes = new byte[] {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
0x00,0x01,0x02,0x03,0x04,0x05
};
private Cipher cipher;
private SecretKeySpec keySpec;
private IvParameterSpec ivSpec;
public SymmethricCipherCBC() throws NoSuchAlgorithmException, NoSuchPaddingException{
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //Utworzenie obiektu dla operacji szyfrowania/deszyfrowania algorytmem AES w trybie CBC.
keySpec = new SecretKeySpec(keyBytes, "AES"); // Utworzenie obiektu klucza dla algorytmu AES z tablicy bajtow
ivSpec = new IvParameterSpec(ivBytes); // // Utworzenie obiektu dla wektora inicjalizacyjnego
}
public String encryptText(String plainText) throws NoSuchAlgorithmException,
InvalidKeyException,
NoSuchPaddingException,
InvalidAlgorithmParameterException,
ShortBufferException,
IllegalBlockSizeException,
BadPaddingException,
UnsupportedEncodingException{
int cipherTextLength;
byte[] cipherText; // Bufor dla szyfrogramu
byte[] plainTextBytes = plainText.getBytes(); // Reprezentacja tekstu jawnego w bajtach
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); //Inicjalizacja obiektu dla operacji szyfrowania z kluczem okreslonym przez keySpec:
cipherText = new byte[cipher.getOutputSize(plainTextBytes.length)]; //Utworzenie buforu dla szyfrogramu
cipherTextLength = cipher.update(plainTextBytes, 0, plainTextBytes.length, cipherText, 0); // Szyfrowanie tekstu jawnego
cipherTextLength += cipher.doFinal(cipherText, cipherTextLength); //Zakonczenie szyfrowania
return new BigInteger(1, cipherText).toString(16); // zapisanie 16
}
public String decryptText(String ciptherTextString) throws InvalidKeyException, InvalidAlgorithmParameterException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{
byte[] cipherTextBytes = ciptherTextString.getBytes();
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); //Inicjalizacja obiektu cipher dla odszyfrowywania z kluczem okreslonym przez keySpec
byte[] plainTextBytes = new byte[cipher.getOutputSize(cipherTextBytes.length)]; // Utworzenie wyzerowanej tablicy
int plainTextLength = cipher.update(cipherTextBytes, 0, cipherTextBytes.length, plainTextBytes, 0);
plainTextLength += cipher.doFinal(plainTextBytes, plainTextLength);
return new String(plainTextBytes); //Odtworzona wiadomosc
}
}
Any ideas what I should do?
Upvotes: 3
Views: 3079
Reputation: 691715
You're doing it harder than necessary, and you're encrypting your cipher text when doing
cipher.doFinal(cipherText, cipherTextLength);
I would rewrite it as is:
public String encryptText(String plainText) throws ... {
byte[] plainTextBytes = plainText.getBytes("UTF8");
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
byte[] encrypted = cipher.doFinal(plainTextBytes);
return toHex(encrypted);
}
public String decryptText(String cipherTextString) throws ... {
byte[] cipherTextBytes = fromHex(cipherTextString);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] plainTextBytes = cipher.doFinal(cipherTextBytes);
return new String(plainTextBytes, "UTF8");
}
Upvotes: 4
Reputation: 3322
as far as I can tell, you are taking the byte array output from the encryption algorithm, and converting it to a hex string using BigInteger. then the decryption algorithm takes the hex string and converts it to the byte representation of the ASCII characters in the hex string using .toString()
This is where your code is wrong (among other places). rather than turning, say, the hex string output "FFFF" into a byte array [0xff, 0xff]
it turns it into the byte array [0x46,0x46,0x46,0x46]
(e.g. the ASCII byte representation of the upper case F). This means that not only will all of the bytes in your conversion be wrong, the byte array will be the wrong length (which causes the exception you listed in your question).
Instead, you should return byte[]
from your encryption method, and accept byte[]
as a parameter in your decryption method. failing that, you should use something like Apache Commons Codec's Hex class to reliably convert between byte arrays and hex strings.
Upvotes: 0