iphone - sistema - IOS: ¿Cómo AES descifra un archivo grande si el archivo es demasiado grande para cargarlo en la memoria?
porque me aparece que el archivo es demasiado grande para el sistema de archivos de destino (2)
Sé cómo cifrar y descifrar un NSData
, pero eso requiere cargar primero todo el archivo en la memoria.
Digamos que tengo un archivo encriptado de 50mb llamado data.dat.enc
, ¿cómo puedo descifrarlo en un archivo data.dat
sin tener que cargarlo primero en la memoria?
EDITAR: Este código se ha ampliado en http://github.com/rnapier/RNCryptor .
RNCryptManager es un buen ejemplo de cómo hacer esto. Viene del Capítulo 11 código de ejemplo de iOS5: PTL . Mirar:
+ (BOOL)decryptFromStream:(NSInputStream *)fromStream
toStream:(NSOutputStream *)toStream
password:(NSString *)password
error:(NSError **)error;
Se supone que la sal y IV se han añadido a la corriente (todo esto se explica en el libro). Para una discusión más general sobre el cifrado AES, consulte Cifrado correcto con AES con CommonCrypto .
Para ver un ejemplo de su uso, vea CPCryptController.m en el mismo proyecto.
Si hay suficiente interés, podría sacar este objeto y apoyarlo como un proyecto independiente en lugar de solo como una pieza de código de muestra. Parece razonablemente útil para las personas. Pero no es tan difícil de integrar como está.
La respuesta más general es que crea un cryptor con CCCryptorCreate
y luego realiza llamadas a CCCryptorUpdate
para cada bloque. Entonces llamas a CCCryptorFinal
para terminar las cosas.
Tiene dos opciones (y aquí describo solo el proceso de cifrado, pero el descifrado es similar):
Utilice un cifrado de flujo (como AES-CTR)
Inicializa el cifrado con una clave de 16 bytes y un código de 16 bytes verdaderamente aleatorio, escribe el nonce, carga la primera pieza, la cifra, escribe el resultado, carga una segunda parte y así sucesivamente. Tenga en cuenta que debe inicializar el cifrado una sola vez. El tamaño de la pieza puede ser arbitrario; Ni siquiera tiene que ser el mismo cada vez.
Utilice un cifrado de bloque con un modo de encadenamiento de una pasada, por ejemplo, AES128-CBC
Inicializa el cifrado con la clave de 16 bytes, genera un IV de 16 bytes al azar, escribe el IV, escribe la longitud total del archivo, carga la primera pieza, la encripta junto con la IV, escribe el resultado, carga la segunda pieza, cifre utilizando los últimos 16 bytes del bloque cifrado anterior como IV, escriba el resultado y así sucesivamente. El tamaño de la pieza debe ser un múltiplo de 16 bytes; De nuevo, ni siquiera tiene que ser el mismo cada vez. Es posible que deba rellenar el último bloque con ceros.
En ambos casos
Debe calcular el hash criptográfico del archivo no cifrado original (por ejemplo, utilizando SHA-256) y escribirlo cuando finalice el cifrado. Eso es bastante fácil: usted inicializa el hash desde el principio y le envía cada bloque tan pronto como se carga (incluyendo nonce / IV y posiblemente el campo de longitud). En el lado del descifrado, haces lo mismo. Finalmente, debe verificar que el resumen calculado coincida con el que vino con el archivo cifrado.
¿Cómo se puede hacer eso en iOS? Me temo que no estoy familiarizado con la plataforma, pero parece que CCCypt encaja a la CCCypt .
EDITAR: Nonce / IV y la longitud también se hash.