IOS - Как мне AES расшифровать большой файл, если файл слишком велик, чтобы загрузить все это в память? - PullRequest
16 голосов
/ 15 марта 2012

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

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

Ответы [ 2 ]

15 голосов
/ 16 марта 2012

РЕДАКТИРОВАТЬ: Этот код был расширен на 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, чтобы закончить.

0 голосов
/ 15 марта 2012

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

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

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

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

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

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

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

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

РЕДАКТИРОВАТЬ: nonce / IV и длина тоже хэшируются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...