Can't fix "Error: Input length must be a multiple of 16 when decrypting with a pad cipher"

StackOverflow https://stackoverflow.com/questions/18326911

  •  25-06-2022
  •  | 
  •  

Question

Ello! I am working a chat application that encrypts it's data through AES/CBC/PKCS5 Padding. It works through the client sending the encrypted message to the server where it is sent back and decrypted. Unfortunately, whenever I decrypt the message, I get the error as follows: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher. The encryption is based of this program :(http://www.scottjjohnson.com/blog/AesWithCbcExample.java) which works perfectly fine and I cannot see the difference between my code and that one except for that I must convert from string to byte array. Here is my code code:

Client (Encryption):

String message = textField.getText();
// generate a key
KeyGenerator keygen = KeyGenerator.getInstance("AES");
keygen.init(128);  // To use 256 bit keys, you need the "unlimited strength" encryption policy files from Sun.
byte[] key = keygen.generateKey().getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

// build the initialization vector.  This example is all zeros, but it 
// could be any value or generated using a random number generator.
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivspec = new IvParameterSpec(iv);

// initialize the cipher for encrypt mode
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);

// encrypt the message
byte[] encrypted = cipher.doFinal(message.getBytes());
System.out.println("Ciphertext: " + encrypted + "\n");
System.out.println(encrypted);
out.println(encrypted);
textField.setText(""); 

Server Side:

String input = in.readLine();
writer.println("MESSAGE " + input);

Client (Decryption):

//DECRYPTION
System.out.println(line);
line = line.substring(8);
System.out.println(line);

// generate a key
KeyGenerator keygen = KeyGenerator.getInstance("AES");
keygen.init(128);  // To use 256 bit keys, you need the "unlimited strength" encryption policy files from Sun.
byte[] key = keygen.generateKey().getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");

// build the initialization vector.  This example is all zeros, but it 
// could be any value or generated using a random number generator.
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivspec = new IvParameterSpec(iv);

// reinitialize the cipher for decryption
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivspec);

// decrypt the message
byte[] decrypted = cipher.doFinal(line.getBytes());
System.out.println("Plaintext: " + new String(decrypted) + "\n");
messageArea.append(name + ": " + decrypted + "\n");
messageArea.setCaretPosition(messageArea.getDocument().getLength());
Était-ce utile?

La solution

Your problem has nothing to do with cryptography. You are failing to transfer your data correctly between your clients and the server.

I'm fairly sure out.println(encrypted) is not what you want to be doing, although I'm not entirely clear since I don't know the type of out. Nor should you be calling line.getBytes() in your decryption code.

You should convert your ciphertext to a non-lossy string form, such as hexadecimal or base64. So, try:

out.println(DatatypeConverter.printHexBinary(encrypted));

and

byte[] decrypted = cipher.doFinal(DatatypeConverter.parseHexBinary(line));
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top