Questa è la prima pagina che viene visualizzata tramite Google e le vulnerabilità della sicurezza in tutte le implementazioni mi fanno rabbrividire, quindi sto postando questo per aggiungere informazioni sulla crittografia per gli altri come sono passati 7 anni dal post originale. Ho conseguito un Master in Ingegneria Informatica e ho trascorso molto tempo a studiare e imparare la crittografia, quindi sto buttando i miei due centesimi per rendere Internet un posto più sicuro.
Inoltre, tieni presente che molta implementazione potrebbe essere sicura per una determinata situazione, ma perché usarli e potenzialmente fare un errore? Usa gli strumenti più potenti che hai a disposizione a meno che tu non abbia un motivo specifico per non farlo. Nel complesso consiglio vivamente di usare una biblioteca e di stare lontano dai dettagli grintosi se puoi.
AGGIORNAMENTO DEL 4/5/18: Ho riscritto alcune parti per renderle più semplici da comprendere e ho cambiato la libreria consigliata da Jasypt alla nuova libreria di Google Tink , consiglierei di rimuovere completamente Jasypt da un'installazione esistente.
Prefazione
Descriverò le basi della crittografia simmetrica sicura di seguito e sottolineerò gli errori comuni che vedo online quando le persone implementano la crittografia da sole con la libreria Java standard. Se vuoi semplicemente saltare tutti i dettagli presenti nella nuova libreria di Google, prova a importarli nel tuo progetto e usa la modalità AES-GCM per tutte le tue crittografie e sarai sicuro.
Ora se vuoi imparare i dettagli grintosi su come crittografare in Java continua a leggere :)
Block Ciphers
Per prima cosa devi scegliere una chiave simmetrica Block Cipher. Un Block Cipher è una funzione / programma del computer utilizzato per creare pseudo-casualità. La pseudo-casualità è una casualità falsa che nessun computer diverso da un computer quantistico sarebbe in grado di dire la differenza tra essa e la casualità reale. Il Block Cipher è come il building block della crittografia e, se utilizzato con modalità o schemi diversi, è possibile creare crittografie.
Ora per quanto riguarda gli algoritmi Block Cipher disponibili oggi, assicurati di MAI , ripeto MAI usare DES , direi MAI MAI 3DES . L'unico Block Cipher che persino la versione NSA di Snowden è stata in grado di verificare di essere il più vicino possibile allo pseudo-casuale è AES 256 . Esiste anche AES 128; la differenza è che AES 256 funziona in blocchi a 256 bit, mentre AES 128 funziona in 128 blocchi. Tutto sommato, AES 128 è considerato sicuro sebbene siano stati scoperti alcuni punti deboli, ma 256 è il più solido possibile.
Fatto curioso DES è stato rotto dalla NSA quando è stato inizialmente fondato e in realtà ha mantenuto un segreto per alcuni anni. Sebbene alcune persone sostengano che 3DES sia sicuro, ci sono alcuni articoli di ricerca che hanno scoperto e analizzato i punti deboli di 3DES .
Modalità di crittografia
La crittografia viene creata quando si prende un codice a blocchi e si utilizza uno schema specifico in modo che la casualità sia combinata con una chiave per creare qualcosa che è reversibile fintanto che si conosce la chiave. Questa viene definita Modalità crittografia.
Ecco un esempio di una modalità di crittografia e la modalità più semplice nota come ECB solo per capire visivamente cosa sta succedendo:
Le modalità di crittografia che vedrai più comunemente online sono le seguenti:
BCE CTR, CBC, GCM
Esistono altre modalità al di fuori di quelle elencate e i ricercatori sono sempre alla ricerca di nuove modalità per migliorare i problemi esistenti.
Passiamo ora alle implementazioni e a ciò che è sicuro. Non usare MAI la BCE, non serve a nascondere i dati ripetuti, come mostrato dal famoso pinguino di Linux .
Durante l'implementazione in Java, tenere presente che se si utilizza il codice seguente, la modalità ECB è impostata per impostazione predefinita:
Cipher cipher = Cipher.getInstance("AES");
... PERICOLO QUESTA È UNA VULNERABILITÀ! e sfortunatamente, questo è visto su StackOverflow e online in tutorial ed esempi.
Nonces e IVs
In risposta al problema riscontrato con la modalità BCE sono stati creati anche i nomi noti come IV. L'idea è che generiamo una nuova variabile casuale e la alleghiamo a ogni crittografia in modo che quando si crittografano due messaggi uguali risultino diversi. Il bello dietro questo è che un IV o un nonce è di dominio pubblico. Ciò significa che un utente malintenzionato può avere accesso a questo, ma fintanto che non hanno la tua chiave, non possono fare nulla con quella conoscenza.
I problemi comuni che vedrò è che le persone imposteranno IV come valore statico come nello stesso valore fisso nel loro codice. ed ecco la trappola per IVs nel momento in cui ne ripeti una, in realtà comprometti l'intera sicurezza della tua crittografia.
Generazione di un IV casuale
SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
Nota: SHA1 è rotto ma non sono riuscito a trovare come implementare correttamente SHA256 in questo caso d'uso, quindi se qualcuno vuole fare un crack e aggiornare questo sarebbe fantastico! Anche gli attacchi SHA1 sono ancora non convenzionali in quanto possono essere necessari alcuni anni su un enorme cluster per rompersi. Scopri i dettagli qui.
Implementazione CTR
Non è richiesta alcuna imbottitura per la modalità CTR.
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
Implementazione CBC
Se scegli di implementare la modalità CBC, fallo con PKCS7Padding come segue:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Vulnerabilità CBC e CTR e perché dovresti usare GCM
Sebbene alcune altre modalità come CBC e CTR siano sicure, si imbattono nel problema in cui un utente malintenzionato può capovolgere i dati crittografati, modificandone il valore quando viene decrittografato. Quindi diciamo che crittografare un messaggio bancario immaginario "Vendi 100", il tuo messaggio crittografato assomiglia a questo "eu23ng" l'attaccante cambia un po 'in "eu53ng" e all'improvviso quando decodifica il tuo messaggio, si legge come "Vendi 900".
Per evitare ciò, la maggior parte di Internet utilizza GCM e ogni volta che vedi HTTPS probabilmente usano GCM. GCM firma il messaggio crittografato con un hash e verifica che il messaggio non sia stato modificato utilizzando questa firma.
Eviterei di implementare GCM a causa della sua complessità. Stai meglio usando la nuova libreria di Google Google Trucco perché di nuovo qui se ripeti accidentalmente un IV stai compromettendo la chiave nel caso con GCM, che è l'ultimo difetto di sicurezza. Nuovi ricercatori stanno lavorando per le modalità di crittografia resistente alla ripetizione IV dove anche se si ripete la IV la chiave non è in pericolo, ma questo deve ancora diventare mainstream.
Ora, se vuoi implementare GCM, ecco un link a una bella implementazione GCM . Tuttavia, non posso garantire la sicurezza o se è correttamente implementato ma riduce le basi. Nota anche con GCM non c'è imbottitura.
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
Chiavi vs password
Un'altra nota molto importante è che quando si tratta di crittografia una chiave e una password non sono le stesse cose. Una chiave nella crittografia deve avere una certa quantità di entropia e casualità per essere considerata sicura. Questo è il motivo per cui è necessario assicurarsi di utilizzare le librerie crittografiche appropriate per generare la chiave per te.
Quindi hai davvero due implementazioni che puoi fare qui, la prima è usare il codice trovato su questo thread StackOverflow per la generazione di chiavi casuali . Questa soluzione utilizza un generatore di numeri casuali sicuro per creare una chiave da zero che è possibile utilizzare.
L'altra opzione meno sicura è usare l'input dell'utente come una password. Il problema di cui abbiamo discusso è che la password non ha abbastanza entropia, quindi dovremmo usare PBKDF2 , un algoritmo che prende la password e la rafforza. Ecco un'implementazione StackOverflow che mi è piaciuta . Tuttavia, la libreria Google Tink ha tutto questo integrato e dovresti approfittarne.
Sviluppatori Android
Un punto importante da sottolineare qui è sapere che il tuo codice Android è retroingegnerizzabile e la maggior parte dei casi lo è anche il codice java. Ciò significa che se memorizzi la password in testo semplice nel tuo codice. Un hacker può recuperarlo facilmente. Di solito, per questo tipo di crittografia, si desidera utilizzare la crittografia asimmetrica e così via. Questo non rientra nell'ambito di questo post, quindi eviterò di immergermi.
Una lettura interessante del 2013 : sottolinea che l'88% delle implementazioni di Crypto su Android sono state eseguite in modo errato.
Pensieri finali
Ancora una volta suggerirei di evitare di implementare direttamente la libreria java per crypto e di utilizzare Google Tink , ti farà risparmiare il mal di testa poiché hanno davvero fatto un buon lavoro nell'implementare correttamente tutti gli algoritmi. E anche allora assicurati di controllare i problemi sollevati sul github di Tink, il popup delle vulnerabilità qua e là.
Se hai domande o feedback, non esitare a commentare! La sicurezza è in continua evoluzione e devi fare del tuo meglio per tenerti aggiornato :)