0

I am building a file encryption utility, here's my encryption code:

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
    for(int i = 0; i < input.size(); i++){
        plainText = input.get(i);
        byte[] b = cipher.doFinal(plainText.getBytes("UTF-8"));
        String outString = new String(b);
        //to be written to file

The strings to encrypt are read in from an array (the utility does other data processing) and then encrypted, and output in an array of strings to write to a file when ready.

When decrypting, I get an error that my padding is wrong. I have been researching and gather that this is down to .getBytes() not returning the byte array exactly as it was. I am reading line by line from file that has been encrypted using my previous code. How can I ensure that my decryption function receives the correct byte array?

Here is the code:

public void decode(File f) throws Exception{
     BufferedWriter out = new BufferedWriter(new FileWriter("Decrypted Archive "+f.getName()+".txt"));
     BufferedReader br = new BufferedReader(new FileReader(f));
     String line;
     while((line = br.readLine())!=null){
         byte[] b = line.getBytes("UTF-8"); 
         line = Decoder.decrypt(b);
         out.write(line+newline);
     }
     br.close();
     out.close();

And the decrypt function:

public static String decrypt(byte[] cipherText) throws Exception{
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
    SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
    cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
    return new String(cipher.doFinal(cipherText),"UTF-8");
  }

Encryption keys etc are all the same.

2 Answers 2

1

String outString = new String(b); will not work. If you must treat cipher as a string then you have to encode it. You can use the printBase64Binary and parseBase64Binary methods in standard Java to convert to and from base64 strings. If you're on Android, you can instead use the android.util.Base64 class.

Also, your encryptor's use of Cipher.doFinal(...) is a little suspicious to say the least. By treating each input as separate plaintext sequence you end up reusing the IV each time. Normally you want to encrypt each input piece with the Cipher.update(...) method, use doFinal(...) when you are all finished.

Sign up to request clarification or add additional context in comments.

Comments

1

The Java library Reader and Writer classes are designed to work with line oriented unencrypted text. However, the text, once encrypted, is no longer text, so treating it as text can cause problems.

What you should do instead is use InputStream and OutputStream classes, which deal with raw data, instead of Reader and Writer classes, for your file access. Edit: In particular, you could use CipherInputStream and CipherOutputStream so you wouldn't have to call the Cipher methods directly. You could also construct an InputStreamReader on the CipherInputStream and an OutputStreamWriter on the CipherOutputStream and just use the read() and write() methods, letting the streams take care of the encryption.

3 Comments

Thank you, I will try this. Can I continue to encrypt as normal and use data streams just for reading in the encrypted file?
@user3289385 Whenever you do new String(...) on ciphertext, you're treating encrypted data as text.
@user3289385 See GregS's comment below if you want to continue to encrypt directly. Alternatively, it might be easier to use CipherOutputStream and CipherInputStream. I've edited my answer to include a discussion on that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.