La falla más grande en este esquema es que depende del código javascript que será transmitido al cliente por el (a) servidor.
Entonces, ¿qué es mantener al servidor (oa un hombre en el medio) para enviar el javascript modificado del cliente que elude todas las medidas de seguridad? ¿Cómo lo sabría el cliente o, en realidad, el usuario? Todo el código que escriba para verificar huellas dactilares, sumas de comprobación, firmas digitales, etc. también puede ser evitado.
Un problema relacionado es otro código javascript malicioso que se ejecuta en su navegador y que no se puede aislar de manera confiable de su código javascript relacionado con la seguridad.
Esto es imposible de arreglar. El Javascript del navegador no es actualmente una plataforma segura y toda la criptografía del lado del cliente del navegador sufre este agujero de seguridad enorme que no se puede cerrar.
Resumen de la discusión en los comentarios sobre la pregunta actualizada
Calcular pw = sha256 (sha256 (user_password)) me parece una mala idea por varias razones.
- AgentMe ya mencionó el primero: no uses hash simple
Funciones como sha-lo que sea para hash de contraseñas. Estas funciones hash fueron diseñadas para ser implementadas eficientemente en hardware y son mucho, mucho
demasiado rapido; Para las contraseñas de hash, quieres funciones de hash lentas. Ver AgentMe
respuesta.
- Con este esquema, pw puede calcularse si conoces gk (que es solo sha256 (user_password)). Entonces, cuando alguien roba su almacenamiento local, le da acceso tanto a la clave de cifrado principal como al token de autenticación / autorización que necesita para descargar los archivos cifrados. Sería mejor mantener los dos secretos independientes uno del otro, de modo que si uno está comprometido por un tercero, no es suficiente calcular el otro y romper la confidencialidad de los datos cifrados.
- Finalmente, no estás agregando tu contraseña de usuario con este esquema. Esto significa que las contraseñas idénticas en toda su base de usuarios producirán valores hash idénticos (y ya hay tablas arco iris grandes para sha-hashes sin sal que contienen los pocos millones de contraseñas más comunes).
Usted sugiere una alternativa, por ejemplo, gk = sha256 (contraseña_usuario) y pw = sha128 (contraseña_usuario). Si bien esto resuelve el punto 2, no aborda 1 y 3. Además, no lo recomendaría porque podría imaginar que proporciona información adicional innecesariamente a un atacante (la misma contraseña con dos valores hash diferentes), aunque No sé cómo explotarlo.
Sugerí usar gk = hmac (user_password, n) y pw = hmac (user_password, m), donde m y n son conocidos, pero diferentes para cada usuario. La forma en que llegue a m y n es irrelevante, siempre y cuando sean aleatorios y suficientemente grandes para que sean únicos en su base de usuarios con una alta probabilidad. Puede crearlos en el cliente y enviarlos para su almacenamiento en el servidor, indexados por el nombre de usuario para que puedan recuperarse en otros clientes. O puede hacer que el servidor los genere cuando el usuario crea una cuenta por primera vez. Los valores no necesitan mantenerse seguros; No valen nada sin la contraseña de usuario. Una mejora mejorada sería usar gk = hmac (bcrypt (user_password), n) y pw = hmac (bcrypt (user_password), m) para hacer que los ataques de fuerza bruta sean más difíciles.
Ahora, no estoy convencido de que esta sugerencia sea una buena idea, ya que hmac está diseñada para la autenticación de mensajes, no para crear tokens de autenticación o claves de cifrado, por lo que tomaría esa sugerencia con un poco de sal. Pero parece resolver los tres puntos que planteo, así que parece una solución mejor que encadenar la misma función hash o usar dos funciones hash diferentes en la contraseña.