Grzesiek
Grzesiek

Reputation: 69

encrypting with AES CBC Java

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

Answers (2)

JB Nizet
JB Nizet

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

Peter Elliott
Peter Elliott

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

Related Questions