Расшифровка зашифрованного файла повреждает файл? Android – Java

Я использую следующий код для шифрования/дешифрования:

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;


public class CryptoUtils {
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES";

    public static void encrypt(String key, File inputFile, File outputFile)
            throws CryptoException {
        doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
    }

    public static void decrypt(String key, File inputFile, File outputFile)
            throws CryptoException {
        doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
    }

    private static void doCrypto(int cipherMode, String key, File inputFile,
                                 File outputFile) throws CryptoException {
        try {
            Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PAdding");
            cipher.init(cipherMode, secretKey);

            FileInputStream inputStream = new FileInputStream(inputFile);
            byte[] inputBytes = new byte[(int) inputFile.length()];
            inputStream.read(inputBytes);

            byte[] outputBytes = cipher.doFinal(inputBytes);

            FileOutputStream outputStream = new FileOutputStream(outputFile);
            outputStream.write(outputBytes);

            inputStream.close();
            outputStream.close();

        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException
                | InvalidKeyException | BadPaddingException
                | IllegalBlockSizeException | IOException ex) {
            throw new CryptoException("Error encrypting/decrypting file", ex);
        }
    }

    public static class CryptoException extends Exception {

        public CryptoException() {
        }

        public CryptoException(String message, Throwable throwable) {
            super(message, throwable);
        }
    }
}

Я могу как зашифровать, так и расшифровать видеофайл. Однако я не могу воспроизвести расшифрованный файл, зашифрованный тем же кодом.

Исходный файл: http://www.megafileupload.com/hSTZ/a.mp4.

Зашифрованный файл: http://www.megafileupload.com/hSU2/encrypted-a.mp4

Расшифрованный файл: http://www.megafileupload.com/hSU1/decrypted-final-a.mp4

Первые 16 байт расшифрованного файла отличаются от исходного файла. Длина такая же.


person manishKungwani    schedule 13.10.2015    source источник
comment
Я не слишком силен в криптографии в java и особенно под Android, но меня беспокоит, что я не вижу, как вы передаете свой IV из функции шифрования в функцию дешифрования. В режиме CBC этот вектор инициализации используется для запутывания первого блока криптографического вывода, поэтому один и тот же обычный текст будет давать совершенно другой криптографический текст даже с тем же ключом. Если вы расшифруете с помощью IV, отличного от используемого при шифровании, расшифровка завершится успешно, но первый блок (16 байт) будет зашифрован. Попробуйте явно указать свой IV (жестко закодируйте его для тестирования, если хотите) и посмотрите, работает ли это.   -  person WDS    schedule 13.10.2015
comment
Я не упомянул о своих подозрениях, но в .NET на С#, если у вас есть режим CBC и вы не укажете свой IV, алгоритм сгенерирует его случайным образом. Обычно вы записываете это как первый блок криптографического вывода, а затем читаете его как первый блок криптографического ввода для использования при подготовке алгоритма для расшифровки. Поэтому либо запишите свой случайный IV в начало выходного файла, либо (только для тестирования) жестко закодируйте его в программе. Обратите внимание, что жестко закодированный IV теряет все полезные свойства, которые существуют для IV. Но в целях тестирования я бы попробовал это.   -  person WDS    schedule 13.10.2015
comment
Не зная, как вы его зашифровали, невозможно понять, в чем проблема с кодом дешифрования. Я не хочу играть в угадайку.   -  person Artjom B.    schedule 13.10.2015
comment
@WDS Я скачал файлы. Действительно, неправильный IV является проблемой, но решение не может быть предоставлено, поскольку вопрос стоит в настоящее время.   -  person Artjom B.    schedule 13.10.2015
comment
@ArtjomB. как я могу добавить туда код соли .. не могли бы вы помочь. Спасибо   -  person manishKungwani    schedule 14.10.2015
comment
привет ты решил эту проблему @manishKungwani   -  person Ravi Vaghela    schedule 14.12.2015


Ответы (1)


Вы предполагаете, что:

  1. Файл помещается в память.
  2. Размер файла вписывается в int.
  3. read() заполняет буфер.
  4. Результат шифрования или дешифрования помещается в память вместе с исходным содержимым.

Нет необходимости ни в одном из этих предположений.

FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream outputStream = new FileOutputStream(outputFile);
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
    byte[] output = cipher.update(buffer, 0, count);
    outputStream.write(output);
}
outputStream.write(cipher.doFinal());
outputStream.close();
inputStream.close();

E&OE, но вы поняли. Вы могли бы сделать свою жизнь еще проще, используя CipherInput/OutputStreams,, но таким образом вы немного теряете связь с крипто-исключениями.

person user207421    schedule 13.10.2015
comment
Спасибо за помощь @EJP, но изменение не сработало .. расшифрованный зашифрованный файл не воспроизводится .. - person manishKungwani; 13.10.2015