Проблема с файлом кодировки ANSI с шифрованием в Linux, Java - PullRequest
1 голос
/ 06 февраля 2020

Я экспортирую базу данных с помощью mysqldump в Ubuntu с помощью java, затем шифрую и дешифрую с помощью Java. Я делаю это со следующими классами Encrypt и Decrypt с Java. Но после расшифровки некоторые символы в начале файла неверны. Вот проблема: enter image description here На первом изображении находится файл, в котором программно есть mysqldump, encrypt и decrypt. На втором - просто mysqldump из той же командной строки. Можете ли вы указать мне направление, что делать? Спасибо

РЕДАКТИРОВАТЬ Я создал соль и сохранил ее в файле, подобном этому:

Шифрование:

        FileInputStream saltFis = new FileInputStream("salt.enc");
        byte[] salt = new byte[8];
        saltFis.read(salt);
        saltFis.close();

        // reading the iv
        FileInputStream ivFis = new FileInputStream("iv.enc");
        byte[] iv = new byte[16];
        ivFis.read(iv);
        ivFis.close();

        SecretKeyFactory factory = SecretKeyFactory.getInstance(secretAlgorithm1);
        KeySpec keySpec = new PBEKeySpec(rsaSecret.toCharArray(), salt, 65536, 256);
        SecretKey secretKey = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), secretAlgorithm2);

        //
        Cipher cipher = Cipher.getInstance(algorithmEncryption);
        cipher.init(Cipher.ENCRYPT_MODE, secret);

        // file encryption
        byte[] input = new byte[64];
        int bytesRead;

        while ((bytesRead = inFile.read(input)) != -1) {
            byte[] output = cipher.update(input, 0, bytesRead);
            if (output != null)
                outFile.write(output);
        }

        byte[] output = cipher.doFinal();
        if (output != null)
            outFile.write(output);

        inFile.close();
        outFile.flush();
        outFile.close();

Расшифровка:

        FileInputStream saltFis = new FileInputStream("salt.enc");
        byte[] salt = new byte[8];
        saltFis.read(salt);
        saltFis.close();

        // reading the iv
        FileInputStream ivFis = new FileInputStream("iv.enc");
        byte[] iv = new byte[16];
        ivFis.read(iv);
        ivFis.close();

        SecretKeyFactory factory = SecretKeyFactory.getInstance(secretAlgorithm1);
        KeySpec keySpec = new PBEKeySpec(rsaSecret.toCharArray(), salt, 65536, 256);
        SecretKey secretKey = factory.generateSecret(keySpec);
        SecretKey secret = new SecretKeySpec(secretKey.getEncoded(), secretAlgorithm2);

        // file decryption
        Cipher cipher = Cipher.getInstance(algorithmEncryption);
        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
        FileInputStream fis = new FileInputStream(decodedB64);
        FileOutputStream fos = new FileOutputStream(outputFile);
        byte[] in = new byte[64];
        int read;
        while ((read = fis.read(in)) != -1) {
            byte[] output = cipher.update(in, 0, read);
            if (output != null)
                fos.write(output);
        }

        byte[] output = cipher.doFinal();
        if (output != null)
            fos.write(output);
        fis.close();
        fos.flush();
        fos.close();
        System.out.println("File Decrypted.");

1 Ответ

2 голосов
/ 06 февраля 2020

О, это просто. Этот идиотский c (но, как ни странно, в большинстве случаев кажется правильным) метод шифрования файлов с использованием CB C хранит IV в отдельном файле, перезаписывая любой старый. Таким образом, если вы перезаписаете или возьмете неверный файл IV, вы получите 16 случайных байтов в начале после расшифровки. Поэтому, если вы не найдете файл IV, который, как мы надеемся, имеет смысл, ваши первые 16 байтов (/ символов) теперь будут потеряны навсегда.

Конечно, любая нормальная программа шифрования хранит соль (пароль и PBKDF2 используются для ключ) и IV в том же файле, что и зашифрованный текст.

Тем не менее, если вам удастся потерять солт-файл или пароль, все данные будут потеряны, так что есть ...


С добавленным кодом проблема становится еще яснее. В режиме шифрования вы забыли создать и использовать IvParameterSpec полностью во время инициализации:

cipher.init(Cipher.ENCRYPT_MODE, secret);

однако из-за способа чтения данных IV вы не получите никакого предупреждения о том, что переменная не используется:

ivFis.read(iv);

Если бы вы создали хороший метод, такой как IvParameterSpec iv = readIvFromFile(), вы бы поймали эту ошибку.


Обратите внимание, что Java ( по умолчанию во включенном провайдере для Cipher) используется полный ноль, поэтому вам повезло, и ваши данные частично не исчезли.

...