Шифрование большого файла с помощью AES с использованием JAVA

Я тестировал свой код с файлами меньше этого (10mb, 100mb, 500mb), и шифрование работает. Однако я столкнулся с проблемами с файлами размером более 1 ГБ. Я создал большой файл (около 2 гб), и я хочу зашифровать его с помощью AES с помощью JAVA, но я столкнулся с этой ошибкой:

"Исключение в потоке" main "java.lang.OutOfMemoryError: Java heap space"

Я попытался увеличить доступную память, используя -Xmx8G, но не кубики. Часть моего кода выглядит следующим образом

    File selectedFile = new File("Z:\\dummy.txt");         
    Path path = Paths.get(selectedFile.getAbsolutePath());       
    byte[] toencrypt = Files.readAllBytes(path);       
    byte[] ciphertext = aesCipherForEncryption.doFinal(toencrypt);
    FileOutputStream fos = new FileOutputStream(selectedFile.getAbsolutePath());
    fos.write(ciphertext);
    fos.close();

Насколько я могу судить, причина, по которой он ведет себя таким образом, заключается в том, что он пытается сразу прочитать весь файл, зашифровать его и сохранить в другой массив байтов вместо буферизации и потоковой передачи. кто-нибудь поможет мне с некоторыми подсказками кода?

Я новичок в кодировании, поэтому я действительно мало знаю, любая помощь будет оценена.

Ответ 1

Даже не пытайтесь читать целые большие файлы в памяти. Шифрование буфера за раз. Просто выполните стандартный цикл копирования с соответствующим образом инициализированным CipherOutputStream, завернутым вокруг FileOutputStream. Вы можете использовать это для всех файлов, не нужно делать из него особый случай. Используйте буфер размером 8k или более.

EDIT "Стандартный цикл копирования" в Java выглядит следующим образом:

byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

где в этом случае out = new CipherOutputStream(new FileOutputStream(selectedFile), cipher).

Ответ 2

Вы также можете упростить процесс, используя Encryptor4j: https://github.com/martinwithaar/Encryptor4j

File srcFile = new File("original.zip");
File destFile = new File("original.zip.encrypted");
String password = "mysupersecretpassword";
FileEncryptor fe = new FileEncryptor(password);
fe.encrypt(srcFile, destFile);

В этой библиотеке используется потоковое шифрование, поэтому она не будет вызывать OutOfMemoryError даже большими файлами. Кроме того, вместо использования паролей вы также можете использовать свой собственный Key.

Посмотрите пример на странице Github здесь: https://github.com/martinwithaar/Encryptor4j#file-encryption