Дешифрирането на шифрован файл поврежда файла? 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 в C#, ако имате режим 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