Tenemos un sitio web donde los usuarios necesitan iniciar sesión para acceder a información privilegiada. Obviamente, estamos utilizando SSL, pero también quiero evitar que las contraseñas de texto sin formato terminen accidentalmente en los registros del servidor o en los ojos errantes de los administradores. Por lo tanto, quiero implementar el hashing del lado del cliente utilizando Javascript.
Además, quiero evitar revelar parejas de usuarios con contraseñas idénticas, por lo tanto, use un salt específico del usuario. Por último, me gustaría agregar un desafío aleatorio (también conocido como nonce) en la mezcla para garantizar que un interceptor * no pueda usar el hash final como la nueva "contraseña". Haré un viaje de ida y vuelta adicional al servidor web para obtener el salt y el desafío antes de iniciar el hashing de contraseñas. *) Sí, estamos usando SSL, pero como defensa en profundidad, me gustaría que la implementación sea lo más sólida posible.
Especialmente el desafío es un reto. La única implementación factible que conozco es primero calcular el hash de la contraseña final (usando bcrypt, scrypt o PBKDF2) y luego hacer una ronda sha256_hmac adicional usando el desafío. En el lado del servidor, obtenemos el hash de contraseña de la base de datos, realizamos el mismo sha256_hmac adicional y comparamos el resultado.
Sin embargo, lo anterior implicaría que el cálculo de hash de la contraseña completa debe realizarse en el lado del cliente en Javascript, porque el hashing en el desafío siempre debe ser el último paso. En un iPhone 3G heredado (?), Solo se pueden realizar 6 rondas de cifrado, o 5000 rondas de PBKDF2-SHA256 en 2 segundos, que es el retraso máximo que podemos tolerar.
Pregunta # 1: ¿Estoy en lo cierto al afirmar que en la actualidad bcrypt debería ser de al menos 12 rondas, y PBKDF2-SHA256 al menos 5000 rondas? ¿Entonces debo elegir las 5000 rondas de PBKDF2-SHA256?
Pregunta n. ° 2: ¿Existen mecanismos de respuesta-desafío que puedan operar antes en el proceso (por ejemplo, con una contraseña de hash), por lo que puedo dejar el endurecimiento de bcrypt / PBKDF2 al servidor web?
Pregunta # 3: Suponiendo que no exista tal mecanismo de desafío-respuesta, ¿es mejor abandonar mi requisito de desafío-respuesta y solo aplicar un lado del cliente de sal específico del usuario y hacer un endurecimiento completo del lado del servidor? ¿Resultaría eso en un sistema más sólido en general que el uso de un mecanismo de desafío-respuesta y menos rondas?
EDITAR: Para resumir el largo camino de comentarios a continuación sobre la seguridad del hashing del lado del cliente en general: la opinión general parece ser que la complejidad agregada no vale la pena y es mejor esforzarse en auditar el servidor. Código lateral y acceso limitado al servidor para personal no confiable.