Как правильно использовать CipherOutputStream для шифрования и дешифрования журнала, созданного с помощью log4j ( RollingFileAppender)

У меня проблема с шифрованием / дешифрованием файла журнала, созданного RollingFileAppender log4j. Для шифрования я попытался расширить RollingFileAppender, просто назовите его EncryptedRollingFileAppender. Я переопределяю метод

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

и в основном использую CipherOutputStream и Base64OutputStream для шифрования и кодирования всего, что записывается в выходной поток. Вот часть кода:

...
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);
...

А затем я расшифровываю файл с помощью этого кода:

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();
}

Он работал, но только частично. Некоторые тексты в результирующем файле были расшифрованы правильно, а некоторые - нет. Если вам интересно, вот что я имею в виду под частично:

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

Я также попытался изменить алгоритм на «DESede», но он все еще был частично расшифрован. Затем я попытался использовать "CBC / PKCS5Padding" на обоих концах, но у меня возникла исключительная ситуация

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

. Я предполагаю, что шифрование не заполняет вход должным образом, но мне интересно, почему ... потому что, когда я использую те же алгоритмы шифрования и дешифрования без CipherOutputStream заполнение работало нормально. Кто-нибудь может помочь мне в этом? Любая помощь будет принята с благодарностью.

PS: Извините за мой английский, это не мой родной язык.

10
задан ordinarydot 7 July 2011 в 16:35
поделиться