Prima di leggere la risposta di @ D.W., è piena di buoni consigli. Quindi, se si desidera eseguire ancora la crittografia basata su password, considerare quanto segue:
- La crittografia basata su password consiste nel trasformare una password in una chiave e quindi usare quella chiave per la crittografia simmetrica.
- Java può eseguire una crittografia basata su password, ovvero eseguire i due passaggi in un'API semplificata, come mostrato here . Tuttavia, consente solo alcune combinazioni di meccanismi di criptaggio della password e algoritmi di crittografia e, in particolare, viene segnalato che non lo consente con AES, che è un problema.
- Niente ti impedisce di eseguire la trasformazione da password a chiave e quindi la crittografia in due passaggi separati nel codice.
Si noti che i meccanismi di hashing delle password di solito non sono coperti dalle leggi crittografiche e dai regolamenti sulle esportazioni, poiché non "nascondono" i dati. Suggerisco quindi di includere solo un'esecuzione di bcrypt nel codice, ad es. jBCrypt che è scritto in Java, OpenSource con una licenza facile e ragionevolmente compatto ( uno file sorgente). Dovresti modificare il codice un po ', perché quell'implementazione vuole usare stringhe , mentre tu vuoi i bit grezzi; quindi, fai quanto segue:
- Utilizza il metodo
crypt_raw()
per convertire la password e il sale nell'output di bcrypt a 192 bit.
- Hash questi 192 bit con SHA-512 (Java 6 include un'implementazione SHA-512). Questo produce 512 bit.
- Utilizza questi 512 bit per la crittografia AES dei tuoi dati, con un MAC sul risultato (ad esempio con HMAC / SHA -256, quindi nuovamente supportato da Java 6). Vedi sotto per i dettagli.
(Di solito preferisco bcrypt su PBKDF2 per le ragioni spiegate ci , ma anche PBKDF2 non è male, quindi se vuoi davvero PBKDF2 (o ne hai bisogno per motivi di conformità), allora vai a prenderlo.)
Importante: eseguire correttamente la crittografia e aggiungere un MAC può essere compromesso in un numero sorprendentemente elevato di modi. sei caldamente incoraggiato a non farlo da solo. Tuttavia, il seguente metodo dovrebbe essere sicuro:
- Hai 512 bit di "dati derivati da password". Suddividilo in quattro blocchi a 128 bit.
- Cifra i dati con AES-128 in modalità CBC. CBC richiede un vettore di inizializzazione , che è una matrice di 16 byte casuali. Utilizzare il primo blocco a 128 bit (dall'uscita SHA-512) come chiave e il secondo blocco a 128 bit come IV. Inoltre, usa il padding PKCS # 5 (dato che i tuoi dati di input possono avere una lunghezza che non è un multiplo di 16).
- Al termine della crittografia, calcolare HMAC / SHA-256 su un input costituito da IV, quindi il risultato di crittografia , in tale ordine; la chiave per HMAC sarà il terzo blocco a 128 bit dell'uscita SHA-512.
- Il "file crittografato" deve contenere il sale per bcrypt (128 bit, ovvero 16 byte), l'output della crittografia AES / CBC e l'output HMAC (256 bit, ovvero 32 byte).
- Per la decrittografia, utilizzare il sale (dal file crittografato) e la password per ricalcolare bcrypt, quindi applicare SHA-512 per ottenere la chiave di crittografia, IV e la chiave per HMAC. Verifica il valore HMAC e, se è corretto, decrittografare i dati.
E, ricorda: mai, mai , MAI riutilizzare il valore salt per due istanze di crittografia (indipendentemente dal fatto che utilizzino o meno la stessa password). Usa sempre java.security.SecureRandom
per generare un salt casuale nuovo ogni volta che desideri crittografare un file.