error on Decryption: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 8 when decrypting with padded cipher

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

Question

Here it is program for encryption and Decryption using DES. program is working when passing the output of encryption directly for decryption. but when taking input from user in string to decrypt, it showing this exception. how to pass cipher string in bytes so it becomes compatible for decryption?

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.DESKeySpec;
import javax.xml.bind.DatatypeConverter;
public class DESEncryptionDecryption {

private static Cipher encryptCipher;
private static Cipher decryptCipher;

public static void main(String[] args) throws InvalidKeySpecException {
try {

String desKey = "0123456789abcdef"; // value from user
byte[] keyBytes = DatatypeConverter.parseHexBinary(desKey);
System.out.println(keyBytes);

SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
SecretKey key = factory.generateSecret(new DESKeySpec(keyBytes));

encryptCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
encryptCipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedData = encryptData("Confidential data"); //String from user

String s=encryptedData.toString();//String input to decrypt From user
byte[] bb=s.getBytes();

decryptCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, key);
decryptData(bb); //Exception

}catch (NoSuchAlgorithmException e) {
       e.printStackTrace();
      } catch (NoSuchPaddingException e) {
       e.printStackTrace();
      } catch (InvalidKeyException e) {
       e.printStackTrace();
      } catch (IllegalBlockSizeException e) {
       e.printStackTrace();
      } catch (BadPaddingException e) {
       e.printStackTrace();
      }}
//method for encryption
private static byte[] encryptData(String data)
       throws IllegalBlockSizeException, BadPaddingException {
      System.out.println("Data Before Encryption :" + data);
      byte[] dataToEncrypt = data.getBytes();
      byte[] encryptedData = encryptCipher.doFinal(dataToEncrypt);
      System.out.println("Encryted Data: " + encryptedData);

      return encryptedData;
     }

//method for decryption

private static void decryptData(byte[] data)
throws IllegalBlockSizeException, BadPaddingException {
byte[] textDecrypted = decryptCipher.doFinal(data); //Exception trigered here
System.out.println("Decryted Data: " + new String(textDecrypted));
}}
Was it helpful?

Solution

I can't easily tell whether this is all that's wrong, but this is definitely wrong:

byte[] encryptedData = encryptData("Confidential data"); //String from user
String s=encryptedData.toString();//String input to decrypt From user
byte[] bb=s.getBytes();

Just decrypt encryptedData instead of of bb. Your s value is basically useless, because you've called toString() on a byte[], which won't give you what you're apparently expecting. The value of s will be something like "[B@15db9742" because arrays don't override toString() in Java.

If you really want to turn arbitrary binary data (such as the result of encryption) into text, use base64 instead. Encode the result of encryption using base64 to get a string, and then later base64-decode it from the string to a byte array, then decrypt that byte array.

Oh, and I'd strongly recommend against using String(byte[]) or String.getBytes() too - always use the overloads which take a character encoding instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top