Cadena hash en c #

91

Tengo un problema al intentar introducir una cadena hash c#.

Ya probé algunos sitios web, pero la mayoría de ellos usa archivos para obtener el hash. Otros que son para cadenas son un poco demasiado complejos. Encontré ejemplos de autenticación de Windows para la web como este:

FormsAuthentication.HashPasswordForStoringInConfigFile(tbxPassword.Text.Trim(), "md5")

Necesito usar un hash para hacer más segura una cadena que contiene un nombre de archivo. ¿Cómo puedo hacer eso?

Ejemplo:

string file  = "username";
string hash = ??????(username); 

¿Debería usar otro algoritmo hash y no "md5"?

Edy Cu
fuente

Respuestas:

183
using System.Security.Cryptography;

public static byte[] GetHash(string inputString)
{
    using (HashAlgorithm algorithm = SHA256.Create())
        return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
}

public static string GetHashString(string inputString)
{
    StringBuilder sb = new StringBuilder();
    foreach (byte b in GetHash(inputString))
        sb.Append(b.ToString("X2"));

    return sb.ToString();
}

Notas adicionales

  • Dado que MD5 y SHA1 son algoritmos obsoletos e inseguros , esta solución utiliza SHA256. Alternativamente, puede utilizar BCrypt o Scrypt como se indica en los comentarios.
  • Además, considere " salar " sus hashes y utilice algoritmos criptográficos probados, como se señala en los comentarios.
Dmitry Polomoshnov
fuente
46
NO USE MD5 O SHA1 , son algoritmos obsoletos e inseguros. Use SHA256 como mínimo o incluso mejor use BCrypt o Scrypt.
Muhammad Rehan Saeed
1
Vea este ejemplo de uso de SCrypt: stackoverflow.com/questions/20042977/…
Muhammad Rehan Saeed
6
@Muh Se puede usar fácilmente para sumas de comprobación, porque es mucho más rápido que SHA512. Pero de hecho para almacenar contraseñas, no se recomienda, lo cual es correcto.
LuckyLikey
5
¿Qué significa esto b.ToString("X2")?
Bilal Fazlani
1
@BilalFazlani ver stackoverflow.com/questions/20750062/…
Hezi
60

La forma más rápida de obtener una cadena hash para almacenar contraseñas es mediante el siguiente código:

    internal static string GetStringSha256Hash(string text)
    {
        if (String.IsNullOrEmpty(text))
            return String.Empty;

        using (var sha = new System.Security.Cryptography.SHA256Managed())
        {
            byte[] textData = System.Text.Encoding.UTF8.GetBytes(text);
            byte[] hash = sha.ComputeHash(textData);
            return BitConverter.ToString(hash).Replace("-", String.Empty);
        }
    }

Observaciones:

  • si el método se invoca con frecuencia, la creación de sha variable debe refactorizarse en un campo de clase;
  • la salida se presenta como una cadena hexadecimal codificada;
andrew.fox
fuente
SHA1Managedla clase no es muy costosa. consume unos 130 bytes y los inicializa a algún valor estático, pero eso es todo. por lo que no debería haber un problema de rendimiento en la mayoría de los casos.
Earth Engine
1
También SHA1Managedes IDisposabley, por lo tanto, requiere envolver su uso en un usingbloque.
Earth Engine
El Disposemétodo de propósito es borrar el búfer interno. Si no lo hace, correrá el riesgo de sufrir un ataque de memoria.
Earth Engine
3
@MuhammadRehanSaeed cuando dije SHA1Managedque no es costoso, quiero decir que su creación no lo es. Además, un algoritmo hash no es necesariamente costoso. Solo tiene que ser (extremadamente) costoso cuando desea encontrar una colisión.
Earth Engine
1
@King_Fisher: ¡es imposible! Hash es una función unidireccional, se pierde información. Si necesita descifrar, debe utilizar un método de cifrado que no sea hash. Por cierto, cifrar las contraseñas es una mala práctica.
andrew.fox
8

Realmente no entiendo el alcance completo de su pregunta, pero si todo lo que necesita es un hash de la cadena, entonces es muy fácil obtenerlo.

Simplemente use el método GetHashCode.

Me gusta esto:

string hash = username.GetHashCode();
Cyril Gupta
fuente
1
Sí, eso es lo que buscas. Pero el código es un gran error. Mostrar escritura como int hash = "username" .GetHasCode ();
Edy Cu
3
¿Por qué ha puesto el nombre de usuario entre comillas dobles? Eso obtendrá el hash de la palabra 'nombre de usuario' y ahora lo que está en la variable de nombre de usuario.
Cyril Gupta
14
no almacene valores de GetHashCode, es diferente para 32x y 64x
Slava
12
Esta es una mala forma de crear un hash de contraseña. Con GetHashCode () no se puede asumir que se generará el mismo número en una computadora diferente. Use el método hash Sha1 o algo así (publicaré un ejemplo más adelante)
andrew.fox
2
Cabe señalar que GetHashCodeno es un algoritmo hash criptográficamente seguro. Use SHA256 como mínimo o incluso mejor use BCrypt o Scrypt para un algoritmo seguro.
Muhammad Rehan Saeed
5

Creo que lo que estás buscando no es hash sino cifrado. Con el hash, no podrá recuperar el nombre de archivo original de la variable "hash". Con el cifrado puede hacerlo y es seguro.

Consulte AES en ASP.NET con VB.NET para obtener más información sobre el cifrado en .NET.

Pieter van Ginkel
fuente
sí, creo que es encriptación, pero solo deseo comparar el hash de resultado. Después de redirigir la página.
Edy Cu
¿Con qué desea comparar el nombre de archivo hash?
Pieter van Ginkel
1
//Secure & Encrypte Data
    public static string HashSHA1(string value)
    {
        var sha1 = SHA1.Create();
        var inputBytes = Encoding.ASCII.GetBytes(value);
        var hash = sha1.ComputeHash(inputBytes);
        var sb = new StringBuilder();
        for (var i = 0; i < hash.Length; i++)
        {
            sb.Append(hash[i].ToString("X2"));
        }
        return sb.ToString();
    }
Soufiane Neffar
fuente
3
NO USE SHA1 desde este enlace, SHA1 es un algoritmo obsoleto e inseguro. Use SHA256 como mínimo o incluso mejor use BCrypt o Scrypt.
Muhammad Rehan Saeed
Vea este ejemplo de uso de SCrypt: stackoverflow.com/questions/20042977/…
Muhammad Rehan Saeed
1

Si el rendimiento no es una preocupación importante, también puede utilizar cualquiera de estos métodos:
(En caso de que desee que la cadena hash esté en mayúsculas, reemplácela "x2"por "X2").

public static string SHA256ToString(string s) 
{
    using (var alg = SHA256.Create())
        return string.Join(null, alg.ComputeHash(Encoding.UTF8.GetBytes(s)).Select(x => x.ToString("x2")));
}

o:

public static string SHA256ToString(string s)
{            
    using (var alg = SHA256.Create())
        return alg.ComputeHash(Encoding.UTF8.GetBytes(s)).Aggregate(new StringBuilder(), (sb, x) => sb.Append(x.ToString("x2"))).ToString();
}
Babak
fuente
0

El camino más corto y rápido de todos los tiempos. ¡Solo 1 línea!

    public static string StringSha256Hash(string text) =>
        string.IsNullOrEmpty(text) ? string.Empty : BitConverter.ToString(new System.Security.Cryptography.SHA256Managed().ComputeHash(System.Text.Encoding.UTF8.GetBytes(text))).Replace("-", string.Empty);
Erçin Dedeoğlu
fuente