-1

I am trying to write a simple app in order to encrypt, and decrypt a chunk of text, using JCA and JCE from Java.

So far the encryption part works, but it gives me the following exception when decrypting :

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

This is the part where I initialize the two Ciphers, encCipher, and decCipher.

PBEKeySpec pbeKeySpec;
PBEParameterSpec paramSpec;
SecretKeyFactory keyFac;
byte[] salt = {(byte) 0xc7, (byte) 0x73, (byte) 0x21, (byte) 0x8c,
               (byte) 0x7e, (byte) 0xc8, (byte) 0xee, (byte) 0x99};
int count = 20;
paramSpec = new PBEParameterSpec(salt, count);

try {
    pbeKeySpec = new PBEKeySpec("my_password".toCharArray(), salt, count);
    SecretKey secretKey = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(pbeKeySpec);

    encCipher = Cipher.getInstance(secretKey.getAlgorithm());
    encCipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
    decCipher = Cipher.getInstance(secretKey.getAlgorithm());
    decCipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec);

} catch (Exception ex) {
    ex.printStackTrace();
 }

I don't have experience with using the Java Cryptography Architecture, I would like to know how could I fix the error.

The exception happens at the line with decCipher.doFinal from loadClients.

private void saveClients() {
   String plainText = "";
   String encText = "";
   Set<String> clients = my_clients.keySet();
        try {
            PrintWriter out = new PrintWriter(new File(output_file));
            for (String client : clients) {
                long client_time = my_clients.get(client);
                plainText = client + " " + client_time;

                encText = new String(encCipher.doFinal(plainText.getBytes()));
                out.println(encText);
            }
            out.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void loadClients() {
        BufferedReader in;
        String line;
        try {
            in = new BufferedReader(new FileReader(output_file));
            while ((line = in.readLine()) != null) {
                byte[] decBytes = decCipher.doFinal(line.getBytes());
                String decText = new String(decBytes);
                String[] client_data = decText.split("[ ]");
                my_clients.put(client_data[0], Long.parseLong(client_data[1]));
            }
            in.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
     }
user852689
  • 751
  • 1
  • 10
  • 21
  • The error is in the code used to encrypt and decrypt. SHow us this code. I tried your code with the following, and it works as expected: byte[] text = "Hello world".getBytes("UTF-8"); byte[] encrypted = encCipher.doFinal(text); byte[] decrypted = decCipher.doFinal(encrypted); System.out.println(new String(decrypted, "UTF-8")); – JB Nizet Dec 26 '11 at 14:40
  • I have added the functions that I use for encrypting and decrypting. Is it possible that the error is because I use BufferedReader for reading and PrintWriter for writing the file instead of OutputStream? – user852689 Dec 26 '11 at 15:21

1 Answers1

1

The problem comes from the fact that you transform bytes into Strings. Suppose that your default platform encoding is ASCII. This means that half of the bytes contained in your encrypted text (bytes 128 and above) don't represent valid characters. Moreover, you write one line for each encrypted text. So, if your encrypted byte array happens to contain a newline char, you will in fact write two lines to the writer, and try to decrypt each line one by one, which will lead to an exception.

Either use bytes to store and transfer your encryted data, or transform them into Strings using a non-lossy algorithm, like Base64 (which will make sure everything will be transformed into printable characters). Apache commons-codec has a Base64 implementation.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255