Por lo general, cuando cambia su contraseña, primero debe ingresar la contraseña anterior. Esto es útil para la seguridad, para garantizar que alguien que pase cerca de su computadora no pueda cambiar la contraseña y bloquearlo rápidamente mientras está de espaldas. También permite que el servidor aplique las reglas de distancia de contraseña. El servidor solo necesita mantener la contraseña anterior en la memoria durante el tiempo que sea necesario para verificar que la nueva contraseña sea lo suficientemente diferente de la anterior. Nunca necesita almacenar la contraseña no dañada, y puede borrar el hash anterior tan pronto como haya almacenado la nueva.
Si el servidor comprueba la igualdad con las contraseñas antiguas, no solo la última, es una historia diferente. Es bastante fácil verificar la reutilización de contraseñas con hashes antiguos: para cada hash antiguo, calcule el hash de la nueva contraseña con el antiguo salt y compárelo con el valor de hash antiguo. En un sistema configurado correctamente, esto debería tomar unos segundos.
Es una cuestión diferente si el servidor está comprobando la similitud con las contraseñas antiguas, y no solo la igualdad con las contraseñas antiguas, sino la similitud con la anterior. Si el servidor utiliza hashes adecuados, debe probar las variaciones de la nueva contraseña y hash de cada variación con todas las sales antiguas. Eso podría tomar minutos o más con un número de variaciones no despreciables. Por lo tanto, si el servidor se queja de la similitud con una contraseña anterior, desconfiaría de que puedan almacenar contraseñas mal escritas.
Hay otro enfoque para la similitud, que es almacenar el hash de cada variación de contraseña, cada una de ellas con sal independientemente, tan pronto como se establece la contraseña. Pero eso no le compra mucho: el servidor todavía necesita calcular el hash de la nueva contraseña con todas estas sales, lo que todavía lleva mucho tiempo, demasiado para un cambio de contraseña típico.
Una forma de recuperar contraseñas antiguas que realmente funciona, pero que nunca he visto implementada en ninguna parte, es hacer lo siguiente en un cambio de contraseña, después de pedirle al usuario la contraseña anterior y antes de borrar la contraseña anterior de la memoria:
- Derive una clave simétrica a partir de la nueva contraseña (usando un algoritmo de fortalecimiento de clave).
- Derive una clave de la contraseña anterior de la misma manera.
- Descifre la lista de contraseñas antiguas con la clave antigua.
- Agregue la contraseña anterior a la lista.
- Haga las comprobaciones de políticas: todas las contraseñas anteriores se conocen en este momento. Si la nueva contraseña pasa las comprobaciones ...
- Cifre la lista de contraseñas antiguas con la nueva clave.
- Cambie la contraseña y la lista cifrada de contraseñas anteriores de la base de datos.
Esto es algo arriesgado porque si la contraseña actual está comprometida, todas las contraseñas anteriores también están expuestas. Pero sí permite aplicar una política de distancia de contraseña a cualquier número de contraseñas anteriores con un esfuerzo de cálculo razonable.