Como señaló @aviv, revelar a un usuario que otro usuario también tiene la misma contraseña es un problema.
Si realmente pretende mantener tales estadísticas, entonces tiene otro problema inherente: el "motor de estadísticas" solo puede ayudar a cualquier atacante, ya que genera una lista de contraseñas que están en uso. Incluso una forma reducida que simplemente dice "esta contraseña ya está siendo utilizada por otra persona" permite al atacante romper las contraseñas mucho más rápido, por la siguiente razón. El buen hashing de contraseñas usa sales para que los atacantes no puedan intentar romper 10 millones de contraseñas en paralelo. Si el hash no tiene sal, el atacante puede hashear una contraseña potencial una vez , y comparar el valor de hash resultante con los 10 millones de hashes; De esa manera, el atacante rompe 10 millones de contraseñas por el costo de romper una. Las sales impiden eso. Las sales son buenas.
Ahora suponga que tiene un motor de estadísticas que le puede decir, cuando un usuario ingrese su nueva contraseña, si esa contraseña ya la está usando otra persona (incluso sin decir cuántos usuarios la han elegido). Luego, un atacante, que podría obtener una copia de su base de datos (las contraseñas de hash, precisamente porque teme ese escenario), puede ejecutar el mismo "motor" en sus propias computadoras. Por lo tanto, puede "enviar" una contraseña potencial al motor y saber si la utiliza uno de los 10 millones de usuarios o no. Esto le permite recortar su enorme lista de contraseñas potenciales a las que realmente valen la pena: en lugar de probar mil millones de contraseñas en cada valor de hash, probará solo las más o menos 1000 contraseñas para las que obtuvo resultados de las estadísticas. motor. Acabas de hacer la tarea del atacante un millón de veces más fácil.
La única forma de salir de este problema es asegurarse de que el atacante nunca podrá acceder a las estadísticas (lo que, a su vez, implica que no serán mostrados a los propios usuarios). Esto sugiere lo siguiente:
-
Cuando un usuario elige su contraseña, la contraseña se revisa como de costumbre (con bcrypt o algo similar).
-
La contraseña está también cifrada asimétricamente con una clave pública RSA dada. El cifrado asimétrico es aleatorio, por lo que los resultados cifrados no permiten ataques de diccionario. Una clave RSA de 2048 bits es suficiente para cifrar elementos de datos de hasta 245 bytes, lo que debería ser suficiente para las contraseñas.
-
La clave privada correspondiente se mantiene en una máquina offline (por lo tanto, presumiblemente inmune a los ataques remotos). A intervalos regulares, el "oficial de estadísticas" recopila las contraseñas cifradas del servidor, las transfiere a la máquina fuera de línea (con una unidad USB o algo similar), las descifra y ejecuta las estadísticas.