2012-08-31 34 views
7

¿Me podría decir si la siguiente es una buena manera de hash de forma segura una contraseña que se almacena en una base de datos:¿Es esta una forma segura de hash de una contraseña?

public string CreateStrongHash(string textToHash) { 

     byte[] salt =System.Text.Encoding.ASCII.GetBytes("TeStSaLt"); 

     Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(textToHash, salt, 1000); 
     var encryptor = SHA512.Create(); 
     var hash = encryptor.ComputeHash(k1.GetBytes(16)); 

     StringBuilder sb = new StringBuilder(); 
     for (int i = 0; i < hash.Length; i++) { 
      sb.Append(hash[i].ToString("x2")); 
     } 

     return sb.ToString(); 

    } 

Muchas gracias de antemano.

+4

Idealmente, creo que debería tener una sal diferente por usuario, y almacenar eso en la base de datos también. – Bridge

+1

Disculpe si estoy siendo un poco denso, pero si alguien obtiene acceso a la base de datos, ¿el almacenamiento de sal no hace que sea más fácil para alguien descifrar el cifrado? – ScubaSteve2012

+0

@ ScubaSteve2012 La sal previene los ataques hash pre calculados ("tablas Rainbow"). Debido a que las contraseñas están saladas, su tabla arcoiris sería inútil para ayudar a descubrir las contraseñas originales. Deberías crear una nueva tabla de arcoíris usando este hash, que es más o menos un ataque de fuerza bruta. – Oleksi

Respuesta

7

Utiliza PBKDF2-SHA1, que es decente, pero no excelente. Bcrypt es un poco mejor, y scrypt es aún más fuerte. Pero como .net ya incluye una implementación incorporada de PBKDF2, esa es una opción aceptable.

Su mayor error es que no entendió la sal. Una sal debe ser única para cada usuario. Es una práctica estándar simplemente crear un valor aleatorio de al menos 64 bits. Almacénelo junto con el hash en la base de datos.

Si lo desea, puede dividir la sal en dos partes. Uno almacenado en la base de datos junto con el usuario, que es diferente para cada uno, y una parte compartida almacenada en otro lugar. Esto gana las ventajas de ambos.

También recomiendo usar un factor de trabajo más alto que 1000. Averigua qué rendimiento es aceptable y ajústate en consecuencia. No iría por debajo de 10000, y en algunas situaciones (encriptación de disco) también es aceptable un millón.

+0

Gracias por su ayuda. – ScubaSteve2012

+0

Si el valor de la sal se almacena, como tal, en la base de datos, es de muy poca ayuda para evitar la colisión. Su utilidad principal en ese caso es evitar que un atacante descubra por inspección que dos usuarios tienen la misma contraseña. Sería mejor utilizar datos que no estén etiquetados específicamente como "sal", o mejor aún, que no estén contenidos en el mismo almacén de datos; el atacante no solo debe comprometer la base de datos que contiene los hashes, sino la base de código y/o un almacén de datos adicional, para determinar qué usar como sal y cómo. – KeithS

+0

@KeithS Nunca mencioné la palabra colisión, porque las colisiones son irrelevantes aquí. El punto principal de una sal es ser único, y así prevenir ataques multi-objetivo. Agregar un secreto que se almacena en ubicaciones separadas es un buen extra, pero no el punto principal de una sal. – CodesInChaos

5

Se puede mejorar. Primero, debe usar bcrypt en su lugar. Los valores hash tradicionales como SHA-512 se pueden romper con bastante facilidad con las GPU de hoy en día. El problema es que estos hash están diseñados para la velocidad, y esto es lo contrario de lo que desea en un hash de contraseña. Bcrypt es un ejemplo de un algoritmo hash adaptativo. Se puede configurar para que tome un tiempo "prolongado" (pero aún así no causará problemas de rendimiento en su sistema) para dificultar la fuerza bruta.

También desea que las sales sean únicas para cada usuario.

Para obtener más información sobre cómo contraseñas hash de forma segura, consulte this question.

+3

Está usando PBKDF2, que es un poco peor que bcrypt, pero sigue siendo una de las funciones recomendadas. – CodesInChaos

+0

SHA-512 es literalmente "lo suficientemente bueno para el trabajo del gobierno"; se considera criptográficamente fuerte y no se conoce ningún "atajo" que reduzca la complejidad de encontrar la solución. El hecho de que cualquier problema pueda resolverse "más rápido" arrojando suficiente hardware es irrelevante; deberías probar 5.2 × 10^72 valores antes de tener una probabilidad de 1 en un * billón * de colisionar con cualquier hash generado previamente. – KeithS

+1

@KeithS Plain SHA-512 no se considera lo suficientemente bueno para aplicaciones como hash de contraseñas, porque es demasiado rápido. En el uso de contraseñas, utiliza funciones deliberadamente costosas para compensar la falta de entropía en una contraseña. | PBKFDF2 con SHA-512 por otro lado es decente. – CodesInChaos

Cuestiones relacionadas