Idealmente , deberíamos hacer la mayoría (¡pero no todas!) del hashing en el lado del cliente.
La necesidad general de hashing de contraseña, con todas las iteraciones y sales involucradas (consulte esta respuesta ), es asegurarse de que el valor almacenado (el" token de verificación de contraseña ") no se pueda usar fácilmente para un ataque de diccionario sin conexión (el atacante intenta una contraseña potencial, hasta que coincida con el se encuentra el valor almacenado). Para que se cumpla la funcionalidad específica de , basta con que el hashing de contraseña lento y con sal se produzca "en algún lugar", y la máquina cliente es un lugar razonable para eso.
Sin embargo, la protección contra ataques de diccionario fuera de línea es solo una parte del objetivo de seguridad. En particular, no queremos que un atacante pueda obtener valores "equivalentes a una contraseña". Si realiza el hashing completo del lado del cliente y almacena el valor "tal como está" en el servidor, un vistazo a la base de datos del servidor (como sucede con demasiada frecuencia con las inyecciones de SQL y las cintas de copia de seguridad perdidas) revelará los valores de hash y permitirá El atacante para iniciar sesión como cualquier usuario inmediatamente. Por lo tanto, aún desea hacer algunos del lado del servidor hash.
Lo que funciona, por ejemplo, es tener el hash lento y salado en el cliente, que resulta en un valor V , y el servidor almacena SHA-256 ( V ). Dado que se ha realizado el hash lento y salado, la protección contra los ataques de diccionario está ahí; y dado que el servidor no almacena V pero aún requiere que el cliente envíe a V para que se le otorgue acceso, las infracciones de solo lectura no se elevan de manera trivial al compromiso total de lectura-escritura.
El hashing del lado del cliente tiene la característica muy interesante de usar recursos del lado del cliente, no del lado del servidor, lo que permite que un servidor determinado procese muchos clientes simultáneos sin quedarse sin CPU, mientras sigue teniendo Un hashing de contraseña lento y salado en general. Sin embargo, esto no se hace a menudo en la práctica debido a algunos inconvenientes:
-
El cliente no puede hacer hash sin conocer la sal, que está almacenada en el servidor. Por lo tanto, el protocolo implica un viaje de ida y vuelta adicional: el cliente debe enviar el nombre de usuario, el servidor responde con el salt y luego (solo entonces) el cliente puede hacer el hash lento y salado.
-
Los clientes son heterogéneos: algunos pueden ser bastante débiles, lo que implica un límite estricto en el número de iteraciones que se pueden aplicar (porque un teléfono inteligente lento como cliente no significa que el usuario humano sea más paciente). Esto es especialmente cierto para los clientes basados en la Web, porque los cálculos de Javascript son muy lentos (en comparación con el código nativo o incluso los applets de Java o Silverlight).
-
El hashing del lado del cliente significa código del lado del cliente, que puede no ser fácilmente actualizado o modificado. Con el hash del lado del servidor, la elección de la función de hash depende completamente del servidor y se puede cambiar sin tener que alterar los clientes instalados de ninguna manera.
-
A algunos servidores les gusta tener acceso a contraseñas de texto simple de vez en cuando, no para el almacenamiento, sino para otras funciones como la detección automática de contraseñas de usuario muy deficientes o el envío de una copia de las contraseñas a las autoridades pertinentes de aplicación de la ley (cuando corresponda). - No estoy diciendo que esto sea bueno o malo , pero cuando se aplica, no está sujeto a una elección por parte de quien diseñe el sistema de inicio de sesión; si está en un país en el que debe permitir que las agencias gubernamentales revisen las contraseñas, entonces, bueno, debe hacerlo, por lo que esto se convierte en un elemento del contexto a tratar).