2012-09-21 24 views
6

Estoy usando Rfc2898DeriveBytes para generar de forma segura la clave de cifrado y el vector de inicialización a partir de la contraseña de cadena suministrada por el usuario, para usar con encriptación simétrica (por ejemplo, AesManaged).¿Está bien usar el hash SHA1 de contraseña como un valor saliente al derivar la clave de cifrado y IV de la cadena de contraseña?

Estoy tomando el hash SHA1 de la contraseña como un parámetro salt a Rfc2898DeriveBytes. ¿Eso esta bien? Si no, ¿de dónde debería obtener la sal? Necesitaré la misma sal cuando descifre, ¿verdad? Así que tengo que guardarlo en algún lugar sin cifrar, no seguro. Si tengo que almacenarlo de forma segura, se convierte en otra "contraseña", ¿no es así?

void SecureDeriveKeyAndIvFromPassword(string password, int iterations, 
    int keySize, int ivSize, out byte[] key, out byte[] iv) 
{ 
    // Generate the salt from password: 

    byte[] salt = (new SHA1Managed()).ComputeHash(Encoding.UTF8.GetBytes(password)); 

    // Derive key and IV bytes from password: 

    Rfc2898DeriveBytes derivedBytes = new Rfc2898DeriveBytes(password, salt, iterations); 

    key = derivedBytes.GetBytes(keySize); 
    iv = derivedBytes.GetBytes(ivSize); 
} 

He visto usar la sal constante (codificada), y he visto personas quejándose de ella. Pensé que derivar la sal de la contraseña sería la mejor idea, pero no estoy seguro de que esta sea una solución óptima.

En breve, tengo un archivo que necesita ser encriptado, y una cadena de contraseñas ingresada por el usuario. ¿Cómo uso correctamente Rfc2898DeriveBytes para derivar clave de encriptación segura y IV?

Gracias.

EDIT:

Gracias por sus respuestas. Ahora entiendo que el principal (¿tal vez solo?) Propósito de la sal es hacer imposible la generación de tablas de arcoiris; no se puede pregenerar el hash de "P @ $$ w0rd" porque tendrá un hash diferente para cada posible valor de sal. Entiendo esto perfectamente, PERO ... ¿Esto es realmente relevante para el cifrado simétrico? No estoy almacenando el hash en ninguna parte, ¿verdad? Entonces, incluso si el atacante tiene la tabla rainbow para todas las posibles combinaciones de contraseñas, no puede hacer mucho, ¿verdad?

Por lo tanto, mi pregunta ahora es: ¿hay alguna ventaja de utilizar la sal al azar en cada operación de cifrado, en comparación con el uso de la contraseña derivado (o modificable incluso) sal, cuando se utiliza con algoritmos de cifrado simétrico (como AesManaged of .NET)?

+0

Es mejor almacenar solo el valor hash de una contraseña. A diferencia de una contraseña cifrada, el valor hash no puede revertirse, incluso si el atacante controla su código y conoce la clave. Entonces, ¿por qué cifrarías la contraseña (PBKDF2 no es encriptación, es hash)? – martinstoeckli

+0

@martinstoeckli, no estoy encriptando la contraseña, ni estoy almacenando su hash en ningún lado. Acabo de derivar la clave de cifrado (y iv) de la contraseña de cadena y luego encriptar la carga útil con ella. –

+0

Creo que ahora entiendo. Primero quiere calcular el hash de la contraseña y luego usar este valor hash para cifrar algunos datos (en lugar de usar la contraseña original directamente). – martinstoeckli

Respuesta

8

Una sal debe ser única para cada contraseña, eso significa crear una contraseña aleatoria para cada contraseña que quiera hash. La sal es no en secreto y se puede almacenar en texto sin formato con el valor hash calculado.

La idea de la sal es que un atacante no puede usar una tabla de arcoiris preconstruida para obtener las contraseñas. Tendría que construir una tabla de arco iris para cada contraseña por separado, y esto no tiene sentido. Es más fácil usar la fuerza bruta, hasta que encuentres una coincidencia.

Hay un ejemplo en MSDN donde se obtiene la sal de la fuente aleatoria del sistema operativo. Esto es lo mejor que puede hacer, para obtener una sal segura, no la derive de su contraseña.

3

Realmente no sé lo que es Rfc2898DeriveBytes pero puedo decirle lo siguiente: la sal no tiene que ser segura. Ahora, dijiste que habías visto gente quejándose de valores constantes codificados y constantes para la sal, y quienquiera que dijera eso es correcto. La sal debe ser un valor aleatorio, nunca una constante, de lo contrario su propósito es derrotado.

¿Entiende para qué se utiliza la sal? Claramente no. Usar el hash como sal es una mala idea porque la contraseña X siempre será salada con el mismo valor Y, una vez más, frustrando su propósito.

+1

RFC 2898 también se conoce como Función de derivación de clave basada en contraseña 2 o PBKDF2. – akton

+0

@akton Gracias. Sin embargo, el problema de TX_ no es entender para qué sirve la sal. –

+0

Solo quería ayudar cuando dijiste "Realmente no sé qué es Rfc2898DeriveBytes". Estoy de acuerdo con su comentario sobre sales derivadas del texto claro o mensaje. – akton

3

A las personas no les gustan las sales codificadas ya que están accesibles para todos los desarrolladores del proyecto (y posiblemente para el público en el caso de proyectos de fuente abierta o ingeniería inversa). Los atacantes pueden calcular tablas de arcoiris para su sal en particular y comenzar a atacar su sistema.

Una buena elección de valor de la sal es algo que:

  • está disponible cada vez que revise la contraseña
  • no cambia entre las comprobaciones de contraseña
  • es diferente para cada uno (o la mayoría) de los cálculos de contraseña

Un nombre de usuario sería una buena elección, siempre que no pueda cambiar. O bien, genere un valor completamente aleatorio cuando cree por primera vez al usuario y almacénelo como sal, junto con los datos del usuario en su base de datos.

4

Una sal está diseñada para proteger contra ataques multiobjetivos haciendo que cada objetivo se comporte de manera diferente. Las tablas del arco iris son solo una encarnación particular de los ataques de múltiples objetivos, donde el esfuerzo computacional se gasta antes de obtener los objetivos.

Existen situaciones en las que se pueden aplicar ataques de varios destinos, pero las tablas de arco iris no.

Un ejemplo de esto: supongamos que está utilizando un esquema de cifrado autenticado con seguridad semántica, como AES-GCM con nonces únicos. Ahora ha obtenido un millón de mensajes diferentes cifrados con una contraseña diferente.

Si utiliza sin sal, para comprobar si una contraseña se aplica a cualquiera de ellos, el atacante necesita uno KDF operación y un millón de descifrado operaciones. Si usa una sal, el atacante necesita operaciones de un millón de KDF y operaciones de un millón de descifrado. Dado que el KDF es lento en comparación con el desencriptado, un ataque contra el primer esquema es mucho más rápido que un ataque en el segundo esquema.

0

Otros ya explicaron el propósito de la sal, y por qué puede ser información pública.

Una parte adicional de la respuesta a su pregunta: no deriva la sal de la contraseña misma. Eso sería muy similar al error de programación que terminó exponiendo millones de contraseñas después del hack de Ashley Madison.

El problema es que cuando utiliza la contraseña para generar el sal, básicamente está haciendo que la contraseña esté disponible en un segundo formulario, y mucho más fácil de descifrar. El atacante puede ignorar por completo la salida de PBKDF2 y simplemente invertir la sal. Eso solo está protegido con SHA1, que ya está roto.

En Ashley Madison, el error fue similar. Las contraseñas se almacenaron en la base de datos principal utilizando bcrypt y se pensó que eran seguras. Pero luego alguien descubrió que las contraseñas para muchas cuentas en realidad se almacenaban dos veces, y la segunda copia solo estaba protegida con MD5.

Cuestiones relacionadas