Come sottolineato da @aviv, rivelare a un utente che un altro utente ha la stessa password è un problema.
Se vuoi davvero mantenere tali statistiche, allora hai un altro problema inerente: il "motore delle statistiche" può solo aiutare qualsiasi aggressore, poiché emette un elenco di password che sono in uso. Anche una forma ridotta che dice semplicemente "questa password è già utilizzata da qualcun altro" consente all'aggressore di violare le password molto più velocemente, per il seguente motivo. L'hashing della buona password utilizza i sali in modo che gli aggressori non possano tentare di violare 10 milioni di password in parallelo. Se l'hashing non è salato, l'utente malintenzionato può cancellare una password una volta e confrontare il valore hash risultante con tutti gli 10 milioni di hash; in questo modo, l'aggressore rompe 10 milioni di password per il costo di rompere uno. I sali lo impediscono. I sali sono buoni.
Ora supponiamo di avere un motore di statistiche che può dirti, quando un utente inserisce la sua nuova password, se tale password è già utilizzata da qualcun altro o meno (anche senza dire quanti utenti l'hanno scelta). Quindi un utente malintenzionato, che potrebbe ottenere una copia del database (le password hash proprio perché temete lo scenario), può eseguire lo stesso "motore" sui propri computer. Pertanto, può "inviare" una potenziale password al motore e sapere se è utilizzata da uno dei 10 milioni di utenti o meno. Ciò gli consente di potare la sua enorme lista di potenziali password fino a quelle che valgono veramente la pena: invece di provare un miliardo di password su ogni valore hash, proverà solo le circa 1000 password per le quali ha ottenuto risultati dalle statistiche motore. Hai appena reso il compito dell'aggressore un milione di volte più facile.
L'unico modo per risolvere questo problema è assicurarsi che l'autore dell'attacco non sia mai in grado di accedere alle statistiche (il che, a sua volta, implica che non verranno mostrate agli utenti stessi). Questo suggerisce quanto segue:
-
Quando un utente sceglie la sua password, la password viene cancellata come al solito (con bcrypt o qualcosa di simile).
-
La password è anche crittografata asimmetricamente con una determinata chiave pubblica RSA. La crittografia asimmetrica è casuale, quindi i risultati crittografati non consentono attacchi di dizionario. Una chiave RSA a 2048 bit è sufficiente per crittografare gli elementi di dati fino a 245 byte, che dovrebbero essere sufficienti per le password.
-
La chiave privata corrispondente viene mantenuta su una macchina offline (quindi presumibilmente immune da attacchi remoti). A intervalli regolari, il "responsabile delle statistiche" raccoglie le password crittografate dal server, le trasferisce sulla macchina offline (con un'unità USB o qualcosa di simile), le decripta e esegue le statistiche.