Si su protocolo de autenticación consiste en enviar al servidor una contraseña, o un hash de la contraseña, con HTTP simple, entonces esto es inherentemente muy débil, por dos razones:
-
Alguien que espía en la línea podría registrar lo que el cliente envía. Si solo enviar estos bytes otorga acceso, entonces el atacante podría simplemente enviarlos nuevamente. Eso es un ataque de repetición . Este problema es lo que alude @AviD en su respuesta. Ninguna cantidad de hash arreglará eso. Algunos protocolos intentan corregir este problema incluyendo un "desafío" del servidor (un valor aleatorio, creado de nuevo para cada conexión), que se debe incluir junto con la contraseña en el cliente; de eso se trata la autenticación del Compendio HTTP .
-
Incluso si la autenticación funcionó, esto sigue siendo HTTP simple, por lo que cualquier información que se envíe después será vulnerable a las escuchas y alteraciones de los atacantes. Si el medio de transporte no está protegido, la autenticación disuadirá solo a los atacantes más sofisticados. Aquí es donde falla el Compendio HTTP.
Por lo tanto, realmente necesita SSL (también conocido como HTTPS), no solo para transmitir su contraseña o hash, sino también el resto de la conversación entre el cliente y el servidor.
En lo sucesivo, asumo que el protocolo se ejecuta dentro de un túnel SSL. Tienes razón al querer usar un hash lento como bcrypt o PBKDF2; tenga en cuenta que también se necesita un salt para evitar el costo compartido (por ejemplo, tablas precomputadas). El hashing lento y salado se utiliza para hacer frente a la debilidad intrínseca de las contraseñas. Ahora, es posible que desee descargar parte del esfuerzo de hash en el cliente. Este puede funcionar, pero plantea algunos problemas prácticos:
-
Dado que el procesamiento de la contraseña debe incluir un salt, uno nuevo para cada instancia de contraseña, entonces el salt debe transmitirse al cliente, de modo que el cliente pueda incluirlo en el hashing que realiza. Esto aumenta la complejidad del protocolo: el cliente primero debe enviar el nombre de usuario al servidor, luego el servidor debe devolver el salt y, solo entonces, el cliente puede comenzar a codificar la contraseña. Este es un viaje de ida y vuelta más a la red que con el habitual "enviar nombre de usuario y contraseña como una solicitud POST".
-
El hashing lento consiste en aceptar gastar una gran cantidad de CPU en cada contraseña, de modo que el atacante también tiene que gastar una gran cantidad de CPU en cada contraseña. Pero si la CPU gastada está en el cliente, no podemos aumentarla tanto como nos gustaría, porque: 1) hay clientes que tienen muy poca CPU (por ejemplo, algunos teléfonos inteligentes o tabletas baratos) y 2) el contexto web implica usar Javascript, y el rendimiento de Javascript es realmente malo cuando se trata de hash (digamos, al menos 20 veces más lento que el código C).
Por lo tanto, lo más habitual es que vale la pena hacer parte del hashing de contraseñas en el cliente.