Prima di tutto, non preoccuparti del nome utente. Il nome utente è supposto essere informazioni pubbliche - se non lo fosse, non sarebbe un nome utente, sarebbe una password. Supponiamo che un utente malintenzionato sia in grado di trovare lo / gli username / i in ogni caso e progetta il tuo sistema in modo da essere sicuro con tale assunto.
In secondo luogo, non preoccuparti del fatto che il metodo di crittografia (o hashing, ecc.) sia pubblico. Questo è principio di Kerckhoff - il metodo di crittografia dovrebbe essere considerato pubblico, l'unica cosa che deve essere segreta dovrebbe essere chiave (o password, in questo caso).
Ci sono molte buone ragioni per questo, non ultimo il fatto che ti permette di pubblicare come funziona il sistema (e quindi convincere i tuoi utenti che è sicuro, o chiedere aiuto agli esperti di sicurezza, o semplicemente usare un esistente sistema standard progettato e analizzato da tali esperti) senza comprometterne la sicurezza.
Terzo, non preoccuparti di salt . Il sale dovrebbe anche essere trattato come (potenzialmente) conoscenza pubblica. Il suo scopo non è quello di fornire alcuna segretezza aggiuntiva, ma di proteggere dagli attacchi utilizzando tabelle hash precompilate assicurandosi che la password di ogni utente venga sottoposta a hash in un modo diverso, anche se le password effettive sono uguali.
OK, quindi che cosa dovrebbe fare ?
Bene, prima di tutto, dovresti utilizzare una funzione di derivazione della chiave sicura che implementa key stretching (e salting, ovviamente) per ricavare la chiave di crittografia dell'utente dalla propria password. PBKDF2 dovrebbe essere utile per questo, sebbene ad es. scrypt potrebbe essere ancora meglio se disponibile.
In secondo luogo, dovresti non ovviamente usare la chiave di crittografia come hash della password. Infatti, non è necessario memorizzare nulla nel database che potrebbe essere utilizzato per ottenere la chiave di crittografia senza conoscere la password. (Ad esempio, la chiave di crittografia non deve essere un hash dell'hash della password.)
Una cosa che potrebbe fare è derivare sia la chiave di crittografia che l'hash della password separatamente dalla password usando PBKDF2, ma sarebbe un po 'inefficiente, dal momento che PBKDF2 è deliberatamente lento. Invece, è possibile ricavare la chiave di crittografia dalla password con PBKDF2 e quindi utilizzare un normale hash crittografico (ad esempio SHA-256) della chiave come hash della password per l'accesso. (Oppure, se si desidera essere più attenti, derivare sia la chiave di crittografia che l'hash della password da una chiave intermedia derivata dalla password che utilizza PBKDF2.)
Infine, per facilitare la modifica della password, non crittografare direttamente i file con la chiave di crittografia dell'utente. Invece, per ogni file, creare una chiave di file casuale, crittografare il file con la chiave del file e crittografare la chiave di file con la chiave di crittografia dell'utente. In questo modo, quando l'utente vuole cambiare la sua password, devi solo crittografare nuovamente le chiavi del file.