2012-03-15 3 views
16

So come AES codificare e decrittografare un NSData, ma ciò richiede il caricamento dell'intero file in memoria prima.IOS - In che modo AES decrittografa un file di grandi dimensioni se il file è troppo grande per caricarlo interamente in memoria?

Dire che ho un file crittografato 50mb chiamato data.dat.enc, come posso decodificarlo su un file data.dat senza dover prima caricarlo tutto in memoria?

+0

Perché non suddividere i dati prima della crittografia, quindi decrittografarli e rimetterli insieme? –

+0

@PRNDLDevelopmentStudios Sì, suppongo che lo farò se devo, ma ho più file di grandi dimensioni, e sarebbe più difficile gestire un gruppo di file divisi. – Kyle

+0

Si potrebbe provare a comprimere i dati prima della crittografia, ma non so se il rapporto di compressione sarebbe abbastanza alto da essere veramente importante. Forse aprire una connessione SSL a un server, caricare i dati crittografati, decrittografare i server e inviarli? –

risposta

15

MODIFICA: questo codice è stato ampliato da http://github.com/rnapier/RNCryptor.


RNCryptManager è un buon esempio di come farlo. Viene dal codice di esempio Chapter 11 di iOS5:PTL. Guardate:

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

Si presuppone che il sale e IV sono stati anteporre al flusso (questo è spiegato nel libro). Per ulteriori discussioni generali sulla crittografia AES, vedere Properly encrypting with AES with CommonCrypto.

Per un esempio del suo utilizzo, vedere CPCryptController.m nello stesso progetto.

Se c'è un interesse sufficiente, potrei estrarre questo oggetto e supportarlo come un progetto autonomo piuttosto che come un pezzo di codice di esempio. Sembra abbastanza utile per le persone. Ma non è così difficile da integrare come-è.

La risposta più generale è che si crea un criptor con CCCryptorCreate e quindi si effettuano chiamate a CCCryptorUpdate per ciascun blocco. Quindi chiami CCCryptorFinal per finire le cose.

+0

+1 Non posso criticare questa risposta. Avrebbe potuto immaginare che ci sarebbe stata una funzione di aggiornamento da qualche parte in qualche modo. –

+0

Appena finito di provarlo. Grazie mille! Funziona perfettamente :) – Kyle

+0

@Rob Nel mio test, ho scoperto che decodificare un file crittografato con la password sbagliata a volte può restituire 'true' da questa funzione (circa lo 0,5% delle volte). Il file "decrittografato" risultante non è realmente decodificato, è solo dati spazzatura, ma la funzione restituisce ancora 'true'. È un comportamento previsto? In tal caso, come posso rilevare se la decrittografia ha avuto veramente successo? – Kyle

0

si hanno due opzioni (e qui mi descrivono solo il processo di crittografia, ma decrittografia è simile):

Utilizzare un cifrario a flusso (come AES-CTR)

si inizializza la cifra con un 16 byte key e veramente random nonce 16 byte, scrivere il nonce, caricare il primo pezzo, crittografarlo, scrivere il risultato, caricare un secondo pezzo e così via. Si noti che è necessario inizializzare il codice una sola volta. La dimensione del pezzo può essere arbitraria; non ha nemmeno bisogno di essere lo stesso ogni volta.

Utilizzare un codice a blocchi con una modalità di concatenamento un passaggio, ad esempio AES128-CBC

inizializzazione della crittografia con la chiave 16 byte, generare un casuale 16 byte IV, prego scrivere la IV, prego scrivere la totale lunghezza del file, caricare il primo pezzo, crittografarlo insieme alla IV, scrivere il risultato, caricare un secondo pezzo, crittografare utilizzando gli ultimi 16 byte del blocco crittografato precedente come IV, scrivere il risultato e così via. La dimensione del pezzo deve essere un multiplo di 16 byte; di nuovo, non ha nemmeno bisogno di essere lo stesso ogni volta. Potrebbe essere necessario eseguire il pad dell'ultimo blocco con gli zeri.

In entrambi i casi

È necessario calcolare l'hash crittografico del file in chiaro originale (ad esempio utilizzando SHA-256) e scrivere quando la crittografia è finito. È piuttosto semplice: si inizializza l'hash all'inizio e si alimenta ogni blocco non appena viene caricato (incluso nonce/IV e probabilmente il campo lunghezza). Al lato della decifratura, fai lo stesso. Alla fine, è necessario verificare che il digest elaborato corrisponda a quello fornito con il file crittografato.

Come può essere fatto su iOS? Temo di non avere familiarità con la piattaforma, ma il CCCypt sembra adattarsi al conto.

MODIFICA: non hash/IV e lunghezza anche hash.

+3

Prima di tutto, ci sono molti problemi con l'uso di RC4, leggere la pagina di Wikipedia. RC4 non usa un IV, sebbene alcune implementazioni possano chiamare qualche elemento un IV. Il secondo paragrafo, che utilizza AES128-CBC, è assolutamente valido come soluzione, ad eccezione del padding con zero. Il solo calcolo di un hash sul testo semplice non è affatto una buona idea, se non altro perché si perderebbero informazioni su detto testo semplice (crittografate due volte lo stesso testo semplice e si possono confrontare i risultati, per citarne uno). –

+0

Se pubblichi la tua soluzione CBC come risposta separata, proponi di utilizzare il padding PKCS # 7 invece dello zero padding. Sarò felice di votare per questo. Questo viene votato a causa dei molti errori aggiuntivi. –

+0

Si noti che il codice originale dell'OP utilizza quasi certamente CBC. È l'impostazione predefinita nelle librerie iOS. Non c'è quasi mai un motivo per usare EBC (l'altra modalità), indipendentemente dal fatto che tu stia criptando/decrittando tutto in una volta o "mentre vai". Il padding PKCS # 7 è anche l'unico padding supportato dalle librerie iOS, quindi è probabile che sia già in uso (a meno che il payload non richieda padding). –

Problemi correlati