Kiara Kiara - 2 months ago 51
Java Question

javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher in tcp

I am using this AES Encrption and decryption method for encrypting my data. There is no problem with udp but when i use tcp i get this error "javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher"

AES Encryption/Decryption Code:

public class AESEncDec {

private static final String ALGO = "AES";
private static final byte[] keyValue = new byte[] { 'T', 'h', 'e', 'B','e', 's', 't','S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };


public static String encrypt(String Data) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = new BASE64Encoder().encode(encVal);
System.err.println("encVal: "+encryptedValue.length());

return encryptedValue;
}

public static String decrypt(String encryptedData) throws Exception {
Key key = generateKey();
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
//byte[] decValue = c.doFinal(encryptedData.getBytes());
String decryptedValue = new String(decValue);
System.err.println("decVal: "+decryptedValue.length());

return decryptedValue;
}
private static Key generateKey() throws Exception {
Key key = new SecretKeySpec(keyValue, ALGO);
return key;
}

}


TCP SERVER CODE:

class TCPServer
{
public static void main(String argv[]) throws Exception
{
AESEncDec edData= new AESEncDec();
// AES edData= new AES();

String msg="Message_";
String clientSentence="";
String capitalizedSentence;
ServerSocket welcomeSocket = new ServerSocket(6789);
Socket connectionSocket = welcomeSocket.accept();
for (int i = 0; i < 10; i++)
{
clientSentence=edData.encrypt(msg+i)+"\n";
DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());
outToClient.writeBytes(clientSentence);
Thread.sleep(100);
}
}
}


TCP CLIENT CODE:

class TCPClient {

public static void main(String argv[]) throws Exception {

AESEncDec edData= new AESEncDec();
String modifiedSentence;
String DecData="";
Socket clientSocket = new Socket("localhost", 6789);
while(true){
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
modifiedSentence = inFromServer.readLine();
DecData=edData.decrypt(modifiedSentence);
System.out.println("FROM SERVER: " + DecData);
}

//clientSocket.close();
}
}


For the Same code when the message is small it gets decrypted correctly. but when the message is long i get the illegalBlocksize Exception.
I tried to use AES/CBC/PKCS5Padding so that the message gets padded and the blocksize comes in a multiple of 16. But still i get either the same error or BadPaddingException. if am specifying PKCS5Padding as the padding technique then the message should be padded correctly and shouldn't be giving this error. why isn't that working. What can i do to decrypt the data correctly. please help..

Answer

The problem is that TCP gives you a stream. If you read a chunk and try to decrypt it, it may fail, because the size of the chunk may not be in multiples of 16 (or 128). AES works on 16 byte or 128 byte chunks of data. So, you may have to wait for a while till you gather that much amount of data before you decrypt.

Since UDP is message oriented, it doesn't face such problem.

@Kiara, Please use the Java8's built-in encoding and see how it works out. Refer here for documentation. Example:

String asB64 = Base64.getEncoder().encodeToString(data.getBytes("utf-8")); 

That was tested to work good with messages of lengths as much as 7 megabytes. It didn't introduce newlines into the encoded messages.

Comments