3

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?

Grzesiek
  • 69
  • 2
  • 8
  • Please provide the stack trace. – tckmn Jan 02 '13 at 15:53
  • same problem as here: http://stackoverflow.com/questions/14109626/javax-crypto-badpaddingexception-unknown-block-type/14109701#14109701 – Henry Jan 02 '13 at 16:13
  • Your encryptText and decryptText methods are clearly incompatible, plus your encryptText method uses an encoding that will fail approximately once every 256 encryptions HINT: Leading zeros are significant in cipher. – President James K. Polk Jan 02 '13 at 19:11
  • See my answer [here](http://stackoverflow.com/questions/4551263/how-can-i-convert-string-to-secretkey/8828196#8828196) which shows you how to handle strings and encryption/decryption. – Maarten Bodewes Jan 02 '13 at 19:50

2 Answers2

4

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");
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
0

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.

Peter Elliott
  • 3,273
  • 16
  • 30