2012-11-16 12 views
8

Il mio team deve sviluppare una soluzione per crittografare i dati binari (memorizzati come byte[]) nel contesto di un'applicazione Android scritta in Java. I dati crittografati verranno trasmessi e archiviati in vari modi, durante i quali non è possibile escludere la corruzione dei dati. Alla fine un'altra applicazione Android (di nuovo scritta in Java) dovrà decifrare i dati.Crittografia dei dati su Android, AES-GCM o semplice AES?

È già stato deciso che l'algoritmo di crittografia deve essere AES, con una chiave di 256 bit. Tuttavia, vorrei prendere una decisione informata su quale implementazione AES e/o "modalità" dovremmo utilizzare. Ho letto qualcosa che si chiama modalità GCM, e ne abbiamo fatto alcuni test (usando BouncyCastle/SpongyCastle), ma non mi è del tutto chiaro su cosa sia esattamente AES-GCM e cosa ci "compra" rispetto al semplice AES - e se ci sono dei trade-off da prendere in considerazione.

Ecco un elenco di preoccupazioni/esigenze/domande abbiamo:

  • Imbottitura: i dati necessari per cifrare non sarà sempre un multiplo di 128 bit, quindi l'attuazione/modalità AES dovrebbe aggiungere padding, ma solo quando necessario. Avevo l'impressione che una semplice implementazione AES, come fornita da javax.crypto.Cipher, non lo avrebbe fatto, ma i test iniziali indicavano che lo faceva. Quindi immagino che il requisito di imbottitura di per sé non sia un motivo per ricorrere a qualcosa come GCM invece di "semplice" AES. È corretto?

  • Autenticazione: Abbiamo bisogno di un metodo infallibile per rilevare se il danneggiamento dei dati si è verificato. Tuttavia, idealmente vogliamo anche rilevare quando la decrittografia viene tentata con una chiave errata. Quindi, vogliamo essere in grado di distinguere tra entrambi questi casi. La ragione per cui alla fine ho considerato GCM era dovuta a questo Stackoverflow question, in cui uno dei rispondenti sembra implicare che questa distinzione è possibile usando AES-GCM, sebbene non fornisca una spiegazione dettagliata (per non parlare del codice).

  • Ridurre al minimo il sovraccarico: È necessario limitare i costi generali di archiviazione e trasmissione dei dati crittografati. Pertanto desideriamo sapere se, e fino a che punto, la scelta di una specifica implementazione/modalità AES influenzi l'ammontare dei costi generali.

  • crittografia prestazioni/decrittazione: Anche se non è una preoccupazione primaria ci si chiede fino a che punto la scelta di una specifica implementazione AES/codifica delle modalità influenze e la decrittografia delle prestazioni, sia in termini di tempo di CPU e della memoria footprint.

Grazie in anticipo per eventuali consigli, chiarimenti e/o esempi di codice.

MODIFICA: delnan indicato utile non esiste una cosa come "AES semplice". Quindi per chiarire, quello che intendevo è usare il supporto AES integrato di Java.
Mi piace così: Cipher localCipher = Cipher.getInstance("AES");

+5

Cos'è "semplice" AES? A meno che non si gestiscano solo 256 bit di dati. Se si dispone di più dati, si utilizza necessariamente * una * modalità. Forse la tua libreria sceglie una modalità per impostazione predefinita (da quello che ho sentito, molte librerie rappresentano una scelta piuttosto insicura qui). Quindi dovresti controllare quale modalità viene effettivamente utilizzata quando utilizzi la "semplice" AES. – delnan

+0

Grazie per il tuo commento @delnan, ho fatto una modifica per chiarire cosa intendevo. – Matthias

risposta

10

Nel 2012 la risposta è di andare su GCM, a meno che non si abbiano seri problemi di compatibilità.

GCM è una modalità autenticata Encryption. Fornisce riservatezza (crittografia), integrità e autenticazione (MAC) in un colpo solo.

Finora, le normali modalità di funzionamento sono state ECB (che è l'impostazione predefinita per Java), CBC, CTR, OFB e alcune altre. Tutti hanno fornito solo la crittografia. La riservatezza di per sé raramente è utile senza integrità; bisognava combinare tali modalità classiche con i controlli di integrità in un modo ad hoc. Poiché la crittografia è difficile da correggere, spesso tali combinazioni erano insicure, più lente del necessario o addirittura di entrambe.

autenticati modalità di crittografia sono stati (abbastanza recentemente) creato da crittografi per risolvere il problema. GCM è uno dei più riusciti: è stato selezionato da NIST, è efficiente, è privo di brevetti e può trasportare Altri dati autentificati (ovvero dati che rimangono in chiaro, ma per i quali è possibile verificare autenticità). Per una descrizione delle altre modalità, vedere this excellent article of Matthew Green.

Venendo alle vostre preoccupazioni:

  • Imbottitura: di default, Java utilizza PKCS # 7 imbottitura. Funziona, ma è spesso vulnerabile a padding oracle attacks che è meglio sconfiggere con uno MAC. GCM incorpora già un MAC (chiamato GMAC).

  • Autenticazione: AES-GCM accetta solo un tasto AES come input, non le password. Vi dirà se il tasto AES è sbagliato o il carico utile è stato manomesso, ma tali condizioni sono considerate come una. Invece, dovresti prendere in considerazione l'utilizzo di un algoritmo di derivazione chiave appropriato come PBKDF2 o bcrypt per ricavare la chiave AES dalla password. Non penso sia sempre possibile dire se la password è errata o se il carico utile è stato modificato, perché i dati necessari per verificare il primo possono sempre essere corrotti. È possibile crittografare una piccola stringa nota (con ECS AES), inviarla e utilizzarla per verificare se la password è corretta.

  • Ridurre al minimo l'overhead: Alla fine della giornata, tutte le modalità portano allo stesso overhead (circa 10-20 byte) se si desidera l'autenticazione. A meno che tu non stia lavorando con payload molto piccoli, questo punto può essere ignorato.

  • Performance: GCM è piuttosto buona in quanto si tratta di una modalità online (non c'è bisogno di tamponare l'intero carico, in modo meno memoria), è parallelizzabile, e richiede una sola operazione AES e una moltiplicazione di Galois per blocco di testo normale. Le modalità classiche come l'ECB sono più veloci (una sola operazione AES per blocco), ma - di nuovo - è necessario anche tenere conto della logica di integrità, che potrebbe risultare più lenta di GMAC.

Detto questo, bisogna essere consapevoli del fatto che la sicurezza GCM si basa su una buona generazione di numeri casuali per la creazione di IV.

+0

Ho appena testato alcuni codici Android usando AES/EAX su Jelly Bean 4.2. Non è riuscito lì con NoSuchAlgorithmException. Questo mi fa meravigliare. C'è una lista di algoritmi ufficialmente supportati? – tiguchi

+0

@ Nobu-games Hai provato il codice in [this security.SO] (http: //security.stackexchange.it/questions/5457/which-type-of-encryption-algorithms-android-supports-and-which-would-be-better) risponde? – SquareRootOfTwentyThree

+0

Ho finito con il raggruppamento di SpongyCastle. In questo modo so che il mio codice di crittografia verrà eseguito su qualsiasi dispositivo Android. Mi ha fatto solo diffidare del fatto che l'ultimo rilascio ufficiale di Android ha eliminato qualcosa che è contenuto in quelli più vecchi (potrei usare AES/EAX su un Samsung Galaxy S con Android 2.3 senza problemi). – tiguchi