Quando l'utente effettua il primo accesso, il tuo software chiederà una nuova password.
A questo punto il DB dovrebbe essere vuoto.
Ora hai UserPassword e un DB vuoto.
Quindi il software genera un nuovo DBdataKey casuale che verrà utilizzato per crittografare / decodificare i contenuti del DB. Per crittografare / decifrare, utilizzare uno dei molti algoritmi noti, come AES o uno simile.
Ora crei 2 string salt salt: PasswordSalt e DBdataKeySalt .
Memorizza PasswordSalt e DBdataKeySalt nel DB come testo in chiaro.
Utilizza una funzione di hash come pbkdf2 (o qualcosa di simile a SHA2 o superiore) con UserPassword e DBdataKeySalt per ottenere un DBdataKeyEncryptionKey
Ora:
DBdataKey è la chiave che utilizzi per crittografare / decodificare il contenuto del DB
DBdataKeyEncryptionKey è la chiave che utilizzi per crittografare / decodificare DBdataKey
Utilizza una funzione di hash come pbkdf2 (o qualcosa di simile a SHA2 o superiore) con UserPassword e PasswordSalt per creare HashedSaltedUserPassword , un hash salato versione di UserPassword , quindi utilizza DBdataKey per crittografare HasedSaltedUserPassword prima di memorizzarlo nel DB.
D'ora in poi puoi utilizzare DBdataKey per crittografare / decrittografare i dati sul / dal DB.
Ora, quando l'utente apre l'applicazione, gli chiedi la password, quindi usa la password inserita con DBdataKeySalt (che viene archiviata in chiaro) per rigenerare DBdataKeyEncryptionKey , quindi utilizza DBdataKeyEncryptionKey ottenuto per decrittografare DBdataKey , quindi puoi utilizzare il DBdataKey decrittografato per leggere il DB.
Ora utilizza DBdataKey per decrittografare HashedSaltedUserPassword e confrontarlo con quello che hai rigenerato utilizzando la password inserita e PasswordSalt (che è memorizzato in testo non crittografato) solo per ricontrollare che le informazioni di accesso siano corrette.
Se l'utente immette la password errata, quando si utilizza DBdataKeyEncryptionKey per decrittografare DBdataKey la funzione di decrittografia fornisce un valore diverso (garbage). L'utilizzo di questo valore (errato) per decrittografare HashedSaltedUserPassword comporterà più valori garbage, che non corrisponderanno all'hash.
Quando l'utente modifica UserPassword , devi solo decrittografare DBdataKey con la vecchia password e ricodificarlo con la nuova password, ma DBdataKey non cambierà, quindi non sarà necessario crittografare nuovamente il contenuto del db quando l'utente cambia la sua password.
Riferimento: non ho inventato nulla, questo è solo un mix di due tecniche ben note:
- Come utente-login & password salting / hashing è fatto
- Come implementare la crittografia del disco al volo (applicata alla crittografia / decodifica del DB)