donde se almacena la sal para "crypto_pwhash" en una aplicación web sin almacenamiento local

3

Estoy desarrollando una aplicación web que almacena datos encriptados en un servidor. Quiero derivar la clave de cifrado y la clave de inicio de sesión de una única contraseña de usuario, por lo que quiero usar libsodiums crypto_pwhash para generar una clave lo suficientemente larga, que pueda dividir en dos. La idea es que el servidor no pueda descifrar los datos cifrados.

Para usar esta función necesita sal. Entiendo que la sal puede no ser secreta, pero se debe almacenar en algún lugar.

  • Si lo guardo en el servidor, se debe recuperar antes de la autenticación (porque es necesario para obtener la clave de inicio de sesión). Esto permitiría probar si existe un nombre de usuario sin conocer su clave de inicio de sesión. No estoy seguro si eso sería un riesgo de seguridad.

  • ¿Podría derivar la sal de otra manera? ¿Qué pasaría si simplemente me diera el nombre de usuario? ¿O la propia contraseña? ¿O correría el riesgo de no tener suficiente entropía?

pregunta Nathan 14.07.2015 - 12:53
fuente

3 respuestas

1

La propiedad requerida de un salt es ser única, ya que hace imposible utilizar la tabla de diccionarios para el hash inverso de todos los usuarios con la misma tabla.

La otra propiedad útil es que sea impredecible, por lo que el atacante no puede calcular previamente la tabla del diccionario antes de obtener la sal. (Escenario donde esto es útil: el atacante detecta un problema de seguridad que puede usar para obtener el hash de la contraseña, genera una tabla para el nombre de usuario al que desea acceder, cuando obtenga la contraseña, puede usarla antes de que pueda reaccionar ante el ataque)

sal aleatoria da las dos propiedades.

Usar el nombre del sitio + nombre de usuario te da la primera propiedad.

la contraseña no te da nada porque al generar una entrada en tu tabla de diccionario, conoces la contraseña (la que hash).

Si lo almacena en el servidor, puede responder a la solicitud con un nombre de usuario no válido mediante un número aleatorio del mismo tamaño de su hash aleatorio (esto es solo un error y absolutamente sin seguridad)

    
respondido por el grandchamp robin 15.07.2015 - 10:18
fuente
1

Creo que la forma de solucionar este problema es separar, en la medida de lo posible, la autenticación y la confidencialidad. La forma ideal de hacer esto sería tener dos contraseñas, una para la autenticación y una completamente independiente para la confidencialidad. El problema es que los usuarios no son ideales. Probablemente harían la misma contraseña o agregarían una cadena muy predecible al final de la cadena de confidencialidad.

La otra cosa que se debe recordar es que, dado que se trata de una aplicación web, asumo que todos los cálculos se realizan en JavaScript que el servidor envía al cliente. Esto hace que tu modelo adversario sea interesante. Si está intentando proteger la confidencialidad de un servidor malintencionado, pero permitiendo que ese servidor le envíe el código (javascript) que ejecutará y que tendrá acceso a la contraseña, realmente no puede protegerse de un servidor malintencionado. Nada impide que el servidor le envíe un javascript que funcione como se esperaba, pero también envía la contraseña al servidor.

Por lo tanto, definitivamente está en un dilema y creo que sin supuestos adicionales y un modelo de adversario mejor definido, no puede proteger la confidencialidad de los datos.

    
respondido por el mikeazo 16.07.2015 - 14:49
fuente
0
  

Si lo guardo en el servidor, se debe recuperar antes de la autenticación [...]

Se recuperaría al mismo tiempo como autenticación, como

select salt, pw_hash from users where name = '@name'

Usarías tanto salt como pw_hash para validar la contraseña que ingresó el usuario. Es posible que aún debas tener cuidado al filtrar información sobre si tu select devolvió un registro o no, pero eso no es complicado por la sal.

Su situación es complicada porque también desea derivar una clave de cifrado a partir de la contraseña del usuario de manera que el servidor no pueda hacer lo mismo. Parte de la confusión se debe a que el usuario tiene una contraseña única que no puede entregar al servidor, pero de alguna manera debe usarse para autenticar al usuario, y por lo tanto, lo que se envíe al servidor no es estrictamente una contraseña. Pero la mayoría de las veces se leen sobre las entradas de sal y hash que se llamarán contraseñas.

Entonces dividamos esto en 2 pasos. El usuario introduce una contraseña. Para la autenticación, el usuario ejecuta algunos KDF sin salt y envía el resultado "C" al servidor. El servidor busca la sal del usuario, procesa la sal y C y compara eso con su hash almacenado. Si tiene éxito, el servidor devuelve la sal (la misma o posiblemente una diferente) al usuario. El usuario combina la contraseña y el salt usando KDF2 para obtener su clave de cifrado. Si los dos KDF son diferentes, o son ajustes entre sí, las dos claves generadas no estarán relacionadas.

    
respondido por el bmm6o 16.07.2015 - 01:17
fuente

Lea otras preguntas en las etiquetas