Una clave con hash con clave y un hash de la contraseña + sal como clave, ¿es seguro?

2

Estaba observando nuestro sistema de autenticación que contiene contraseñas de forma diferente a las que me enseñaron. La sal es una matriz de bytes constante y usa la contraseña + la sal como clave para el algoritmo de hashing de contraseña.

public byte[] GetHash (string password)
{
    var hmac = KeyedHashAlgorithm.Create("HMACSHA512");
    hmac.Key = HashAlgorithm.Create("SHA512").ComputeHash(this.salt + password);
    return hmac.ComputeHash(password);
}

Eliminé la conversión a matrices de bytes, pero simplemente puse,

var hash = keyedHash(hash(salt+password), password);

¿Es esta una forma segura de hashear la contraseña? Siempre me dijeron que se debería generar sal cada vez que una contraseña se revisa y almacena junto con la contraseña.

    
pregunta user38044 28.01.2014 - 03:14
fuente

2 respuestas

3

Este método de hash es una construcción hecha a mano que, como casi todas las construcciones hechas a mano, es débil.

En este caso, comete los dos pecados cardinales del hashing de contraseña:

  • La función de hash permite ataques paralelos.
  • La función de hash es demasiado rápida.

Aquí, si dos usuarios tienen la misma contraseña, terminan con el mismo hash. Esto significa que si el atacante tiene mil hashes de contraseña para trabajar (por ejemplo, volcó la tabla de la base de datos correspondiente a través de alguna inyección de SQL), entonces puede codificar una contraseña potencial y buscar el valor de hash en la tabla: el atacante ataca 1000 contraseñas simultáneamente, por aproximadamente el mismo costo de atacar a uno. Esto es muy malo. Las sales están destinadas a evitar eso, pero esto solo funciona si cada sal se usa para una contraseña de hash, no para todas las contraseñas de hash en un servidor determinado.

En cuanto a la velocidad: una PC básica pasará por varias millones de SHA-512 instancias por segundo. No muchas contraseñas elegidas por el usuario resisten durante mucho tiempo cuando el atacante puede probar millones por segundo ...

La sugerencia de @ paj28 es algo mejor, pero no tan óptima como se podría desear. El uso de un hash del nombre de usuario concatenado con un valor global del servidor (pero distinto de un servidor a otro) garantiza algún tipo de singularidad mundial; sin embargo, si un usuario cambia su contraseña, usará la misma "sal" (ya que está en el mismo servidor y el usuario no cambió los nombres, solo las contraseñas). El atacante que podría obtener los hashes de la contraseña antigua y la nueva aún podrá atacar a ambos en paralelo. Esto es mejor que el método anterior, pero aún no es perfecto.

Además, el problema de la velocidad se mantiene y es lo suficientemente serio como para justificar un anatema en esta propuesta.

Lea esta respuesta para saber cómo debe ser la contraseña hash, y qué conceptos teóricos están trabajando aquí. La respuesta corta es: use bcrypt .

    
respondido por el Tom Leek 28.01.2014 - 15:11
fuente
1

¿Supongo que la sal es constante en todos los usuarios? Si bien eso es mejor que no tener sal en absoluto, todavía hace que un ataque de fuerza bruta sea más fácil, ya que pueden forzar a todas las cuentas de usuario a la vez. También revela cuando dos usuarios tienen la misma contraseña.

Sin embargo, considera esta pequeña variación:

hash = keyedHash(hash(system_salt+username), password);

Esto es básicamente correcto. Normalmente no lo recomendaría, es más conservador usar sales aleatorias por usuario, pero le otorga las propiedades requeridas de una sal.

    
respondido por el paj28 28.01.2014 - 11:24
fuente

Lea otras preguntas en las etiquetas