Как добавить и получить определенное количество байтов из файла, используя потоки ввода и вывода файла? - PullRequest
0 голосов
/ 11 января 2019

Я работаю над классом для шифрования / дешифрования больших файлов, поэтому я пытаюсь использовать потоки вместо байтовых массивов, чтобы избежать исключений OutOfMemory. В методе шифрования я добавляю случайную соль и iv в начало зашифрованного файла, и он работает нормально, а вот код:

public File encryptFile(File inputFile, File outPutFile, String password, ProgressBar progressBar, Label progressPercentage){
        //Create IV
        byte[] ivBytes = new byte[16];
        SecureRandom random1 = new SecureRandom();
        random1.nextBytes(ivBytes);
        IvParameterSpec iv = new IvParameterSpec(ivBytes);


        //Create the key with the salt
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[SALT_SIZE];
        random.nextBytes(salt);

        SecretKeySpec keySpec = generateAesKey(password, salt);

        //Create and Init the cipher
        Cipher c = Cipher.getInstance("AES/CBC/"+padding);
        c.init(Cipher.ENCRYPT_MODE, keySpec, iv);

        byte[] buf = new byte[8192];
        FileInputStream in = new FileInputStream(inputFile);
        FileOutputStream out = new FileOutputStream(outPutFile);
        int nread;
        int progress = 0;

        byte[] ivAndSalt = new byte[ivBytes.length + salt.length];
        System.arraycopy(ivBytes,0, ivAndSalt,0, ivBytes.length );
        System.arraycopy(salt, 0, ivAndSalt, ivBytes.length, salt.length);
        out.write(ivAndSalt);

        while((nread = in.read(buf)) != -1) {
            byte[] enc = c.update(buf, 0, nread);
            out.write(enc);
            progress++;
        }

Затем я пытаюсь получить iv и соль в методе расшифровки, а затем расшифровать оставшуюся часть файла в выходной файл с помощью FileInputStream.getChannel.position():

 public File decryptFile(File inputFile, File outPutFile, String password, ProgressBar progressBar, Label progressPercentage) {
        //Create and Init Cipher
        Cipher c = Cipher.getInstance("AES/CBC/" + padding);

        FileInputStream in = new FileInputStream(inputFile);
        FileOutputStream out = new FileOutputStream(outPutFile);

        //Getting the iv and salt
        byte[] ivBytes = new byte[16];
        byte[] salt = new byte[SALT_SIZE];
        byte[] ivAndSalt = new byte[ivBytes.length+SALT_SIZE];
        in.read(ivAndSalt, 0, ivBytes.length+SALT_SIZE);
        System.arraycopy(ivAndSalt, 0, ivBytes, 0, ivBytes.length);
        System.arraycopy(ivAndSalt, ivBytes.length, salt, 0, SALT_SIZE);
        IvParameterSpec iv =new IvParameterSpec(ivBytes);
        SecretKeySpec keySpec = generateAesKey(password, salt);
        c.init(Cipher.DECRYPT_MODE, keySpec, iv);


        in.getChannel().position(ivAndSalt.length);

        int nread;
        int progress = 0;
        byte[] buf = new byte[8192];

        while((nread = in.read(buf)) != -1) {
                byte[] enc = c.update(buf, 0, nread);
                out.write(enc);
                progress++;

            /*if (enc.length / 8192 != 0)
                    System.out.println((nread*progress) + "%");*/
        }
        System.out.println("Size of out before doFinal(): " + out.getChannel().size());
        byte[] enc = c.doFinal();
        out.write(enc);
        System.out.println("Size of out after doFinal(): " + out.getChannel().size());
        return  outPutFile;
    } 

Я не получил ошибку при вызове decryptFile (), но созданный файл поврежден, и это означает, что где-то в расшифровке существует проблема.

1 Ответ

0 голосов
/ 12 января 2019

Проблема была совершенно глупой, я забыл закрыть входной и выходной потоки после doFinal() и записать массив байтов в вывод:

in.close();
out.close();
...