Digamos que tengo un sistema donde uno de los requisitos de seguridad es evitar que los usuarios elijan una contraseña que coincida con su nombre de usuario. Los nombres de usuario no distinguen entre mayúsculas y minúsculas, pero las contraseñas son. El servidor almacena las contraseñas mediante una función de hash segura que no se puede revertir.
Cuando se crea la cuenta, tanto el nombre de usuario como la contraseña están inicialmente disponibles en texto simple al servidor para comparación. Podemos compararlos en la memoria (sin tener en cuenta el caso) para ver si coinciden e instruir al usuario para que elija una contraseña diferente si lo hacen. Una vez que se cumple con esta verificación, la contraseña se oculta de forma segura para el almacenamiento, mientras que el nombre de usuario se guarda en texto sin formato. No hay problemas para cumplir el requisito aquí.
Cuando el usuario desea cambiar su contraseña, o si se la están cambiando, el servidor puede recuperar su registro de nombre de usuario y compararlo con el valor de la contraseña recién elegida (nuevamente ignorando el caso) para ver si coincide. No hay problemas para cumplir el requisito aquí tampoco.
Sin embargo, el sistema también permite cambios de nombre de usuario. Durante este proceso de cambio de ID, el usuario no necesariamente ha proporcionado su contraseña en texto simple al servidor. Es posible que lo hayan hecho cuando se autenticaron, pero el servidor no mantendrá esa contraseña almacenada en texto sin formato en caso de que decidan cambiar su nombre de usuario. Por lo tanto, la contraseña de texto sin formato no está disponible para verificar una coincidencia con el nuevo valor de nombre de usuario elegido.
En un intento por cumplir con nuestro requisito, el servidor puede usar la misma función de hashing seguro para codificar el nuevo nombre de usuario y compararlo con la contraseña de hash registrada. Si coinciden, el servidor puede indicar al usuario que elija un nombre de usuario diferente. Sin embargo, dado que el nombre de usuario no distingue entre mayúsculas y minúsculas, esta verificación puede fallar cuando es discutible. Si envío "PwdRsch1" como una nueva opción de nombre de usuario y mi contraseña es "pwdrsch1", el sistema lo permitirá ya que los hashes no coincidirán. Yo, o lo que es peor, un atacante, luego podría autenticarse con éxito con un nombre de usuario y contraseña coincidentes de "pwdrsch1".
Podríamos forzar el nombre de usuario a minúsculas antes de aplicar hash y verificarlo con la contraseña, pero entonces es posible el escenario inverso. El nombre de usuario se verificará como "pwdrsch1" con una contraseña de "PwdRsch1" y se permitirá ya que no coinciden. Pero luego puedo autenticarme con éxito con un nombre de usuario y contraseña coincidentes de "PwdRsch1".
¿Qué opciones razonables tengo para reducir el riesgo de que una contraseña coincida con un nombre de usuario que no distinga mayúsculas y minúsculas?