IOS. Как AES расшифровывать большой файл, если файл слишком велик, чтобы загрузить его все в память? - программирование
Подтвердить что ты не робот

IOS. Как AES расшифровывать большой файл, если файл слишком велик, чтобы загрузить его все в память?

Я знаю, как AES шифрует и расшифровывает NSData, но для этого требуется сначала загрузить весь файл в память.

Скажем, у меня есть зашифрованный файл размером 50 МБ под названием data.dat.enc, как я могу его дешифровать в файл data.dat без необходимости сначала загружать его все в память?

4b9b3361

Ответ 1

EDIT: этот код был расширен http://github.com/rnapier/RNCryptor.


RNCryptManager - хороший пример того, как это сделать. Он исходит из примера кода главы 11 iOS5: PTL. Посмотрите:

+ (BOOL)decryptFromStream:(NSInputStream *)fromStream
                 toStream:(NSOutputStream *)toStream
                 password:(NSString *)password
                    error:(NSError **)error;

Предполагается, что соль и IV были добавлены к потоку (все это объяснено в книге). Для более общей дискуссии о шифровании AES см. Правильное шифрование с помощью AES с помощью CommonCrypto.

Пример его использования см. в CPCryptController.m в том же проекте.

Если есть достаточный интерес, я мог бы вытащить этот объект и поддержать его как автономный проект, а не как образец кода образца. Это кажется разумно полезным для людей. Но это не так сложно интегрировать как есть.

Более общий ответ заключается в том, что вы создаете криптор с CCCryptorCreate, а затем делаете вызовы CCCryptorUpdate для каждого блока. Затем вы вызываете CCCryptorFinal, чтобы закончить работу.

Ответ 2

У вас есть два варианта (и здесь я описываю только процесс шифрования, но дешифрование аналогично):

Использовать потоковый шифр (например, AES-CTR)

Вы инициализируете шифр с 16-байтовым ключом и по-настоящему случайным 16-байтным nonce, записываете nonce, загружаете первую часть, шифруете ее, записываете результат, загружаете вторую часть и так далее. Обратите внимание, что вы должны инициализировать шифр только один раз. Размер куска может быть произвольным; это даже не обязательно должно быть одинаковым каждый раз.

Используйте блок-шифр с режимом цепочки с одним проходом, например AES128-CBC

Вы инициализируете шифр с 16-байтовым ключом, генерируете случайный 16-байтовый IV, записываете IV, записываете общую длину файла, загружаете первую часть, шифруете ее вместе с IV, записываете результат, загружаете второй фрагмент, зашифруйте с использованием последних 16 байтов предыдущего зашифрованного блока как IV, запишите результат и т.д. Размер фрагмента должен быть кратным 16 байтам; опять же, это не обязательно должно быть одинаковым каждый раз. Возможно, вам понадобится заполнить последний блок нулями.

В обоих случаях

Вы должны вычислить криптографический хеш исходного незашифрованного файла (например, используя SHA-256) и записать его, когда шифрование завершено. Это довольно просто: вы инициализируете хеш в самом начале и загружаете каждый блок в него, как только он загружается (в том числе nonce/IV и, возможно, поле длины). На стороне расшифровки вы делаете то же самое. В конце концов, вы должны убедиться, что вычисленный дайджест соответствует тому, который пришел с зашифрованным файлом.

Как это можно сделать на iOS? Я боюсь, что я не знаком с платформой, но CCCypt, похоже, соответствует счету.

EDIT: nonce/IV и длина также хэшируются.