10

I have a problem in encrypting/decrypting log file generated by log4j's RollingFileAppender. For the encryption I have tried to extend the RollingFileAppender, just call it EncryptedRollingFileAppender. I override the method

setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)

and basically I use CipherOutputStream and Base64OutputStream to encrypt and encode everything written to the output stream. Here's part of the code:

...
setImmediateFlush(true);

FileOutputStream ostream = null;
CipherOutputStream cstream = null;
Base64OutputStream b64stream = null;
try {        
    byte[] keyBytes = "1234123412341234".getBytes();  //example
    final byte[] ivBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 
         0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; //example

    final SecretKey key = new SecretKeySpec(keyBytes, "AES");
    final IvParameterSpec IV = new IvParameterSpec(ivBytes);
    final Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, key, IV);

    ostream = new FileOutputStream(fileName, true);
    b64stream = new Base64OutputStream(ostream);
    cstream = new CipherOutputStream(b64stream, cipher);

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

Writer cw = createWriter(cstream);
...

And then i decrypt the file with this code:

private static void decryptFile(String filename) throws Exception {
    FileInputStream fis = null;
    BufferedReader br = new BufferedReader(new FileReader(filename));

    File file = new File(filename + "-decrypted");
    file.createNewFile();
    Writer out = new OutputStreamWriter(new FileOutputStream(filename + "-decrypted"), "UTF-8");

    String line = null;
    try {
         while (( line = br.readLine()) != null){
             line = decrypt(Base64.decodeBase64(line));
             out.write(line);
         }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (br != null) {
            br.close();
        }
        if (fis != null) {
            fis.close();
        }
        if (out != null) {
            out.close();
        }
    }
}

public static String decrypt(byte[] line) throws Exception {
    byte[] keyBytes = "1234123412341234".getBytes();
    final byte[] ivBytes = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
                0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

    final SecretKey secretkey = new SecretKeySpec(keyBytes, "AES");
    final IvParameterSpec IV = new IvParameterSpec(ivBytes);
    final Cipher decipher = Cipher.getInstance("AES/CFB8/NoPadding");
    decipher.init(Cipher.DECRYPT_MODE, secretkey, IV);
    final byte[] plainText = decipher.doFinal(line);

    return new String(plainText, "UTF-8").trim();
}

It worked but only partially. Some texts in the result file were decrypted correctly but some others were not. If you're curious, this is what I mean by partially:

07 Jul 11 13:13:13, DEBUG  MrBean.java:checkUserVal���̥V;��ƃ�˨�� - username: squall,password: 4GROmr95Qcf����v�M�7�y�5�@CGO09 ,active: true 

I also have tried changing the algorithm to "DESede" but it was still partially decrypted. Then I tried to use "CBC/PKCS5Padding" in both ends but I got an exception

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

I assume the encryption is not properly padding the input but I wonder why... because when I use the same encryption and decryption algorithms without the CipherOutputStream the padding worked just fine. Anyone can help me to make this works? Any help will be appreciated.

PS: Sorry for my English, it's not my native language.

ordinarydot
  • 147
  • 1
  • 2
  • 7
  • Just curious: why would you use Base64OutputStream? Normally encrypted files are in binary format and there's no advantage in making them ascii. – Tim Cooper Sep 22 '14 at 06:07
  • Just a thought, wouldn't you need `CipherInputStream` for decryption? – Jus12 Aug 03 '15 at 13:10

1 Answers1

4

Looks pretty good. Are you resetting/initializing the cipher object for every message? You probably don't want to do that, but if you do then you need to think carefully about the structure of the cipher file, because the decryptor needs to know where the message boundaries are.

President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
  • Not for every message, but I think there are some cases where the cipher is reinitialized. It shouldn't be a problem if the key, IV, algorithm, block cipher mode and padding weren't changed, right? (just like example code above) – ordinarydot Jul 07 '11 at 15:58
  • 2
    It is a problem. To simplify greatly, the "IV" you need to use is different for different positions in the cipher stream. See the [wikipedia page](https://secure.wikimedia.org/wikipedia/en/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29) for details – President James K. Polk Jul 07 '11 at 23:53
  • Thanks for reply. Hm, I thought it would work if I use the same IV, it was only for testing anyway. But if it must be different, that would make everything more complicated I guess. I must write the IV in the file, add message delimiter, etc. What about the padding that didn't work? Do you have any clue? – ordinarydot Jul 08 '11 at 03:39
  • @ordinarydot: I agree, using separate message entities is much more complicated. The NoPadding works fine, the problem is almost certainly entirely due to reseting the the cipher instance. – President James K. Polk Jul 08 '11 at 10:44
  • It's already working now. I took a different approach though. Now I extends all the classes to log4j's WriteAppender and then I simply put all the encryption and encoding directly in the writers. Dealing with CipherOutputStream with no knowledge what's going on is too much I guess. Now I used AES/ECB/PKCS5Padding but I plan to change it to CBC. Use different IV for each message and add necessary changes. Well, thanks a lot Greg, for all the help. – ordinarydot Jul 08 '11 at 14:33
  • Oh yeah, I didn't use the NoPadding because there were still incorrectly decrypted part. Only a small part though, unlike before, in the end of some line. – ordinarydot Jul 08 '11 at 14:42
  • I've got the same problem. Is there a solution ? – Evgeniy Mishustin Jul 07 '16 at 09:40