Hash con el algoritmo SHA1 en C #

84

Quiero hash dada una byte[]matriz usando SHA1Algoritmo con el uso de SHA1Managed.
El byte[]hash vendrá de la prueba unitaria.
El hash esperado es 0d71ee4472658cd5874c5578410a9d8611fc9aef(distingue entre mayúsculas y minúsculas).

¿Cómo puedo conseguir esto?

public string Hash(byte [] temp)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {

    }
}
Merve Kaya
fuente
1
Su excpected de hash es un valor hexadecimal, por lo que no importa si es el caso por ejemplo a situacioneshex(e) == hex(E)
JAC

Respuestas:

170

Para aquellos que desean un formato de texto "estándar" del hash, pueden usar algo como lo siguiente:

static string Hash(string input)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {
        var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input));
        var sb = new StringBuilder(hash.Length * 2);

        foreach (byte b in hash)
        {
            // can be "x2" if you want lowercase
            sb.Append(b.ToString("X2"));
        }

        return sb.ToString();
    }
}

Esto producirá un hash como 0C2E99D0949684278C30B9369B82638E1CEAD415.

O para una versión con código de golf:

static string Hash(string input)
{
    var hash = new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(input));
    return string.Concat(hash.Select(b => b.ToString("x2")));
}
Mitch
fuente
Me molesta que esta solución no elimine el objeto SHA1Managed, porque está marcado como Desechable. Esta publicación podría ser útil al optimizar: stackoverflow.com/a/624379/991863
sky-dev
@ sky-dev, por lo general estoy de acuerdo IDisposable, pero un viaje rápido a la fuente de referencia muestra que no sucede nada interesante en.Dispose()
Mitch
Sí, también miré la implementación de Dispose. Solo aceleraría un poco la recolección de basura. Probablemente no sea gran cosa en el gran esquema de las cosas.
sky-dev
21
@Mitch Si implementa la interfaz IDisposable, lo que suceda en la fuente de referencia no debería importar. Si alguna vez lo cambian por alguna razón, de modo que la llamada .Dispose () se vuelva importante, su código que funcionaba anteriormente ahora está causando un problema. Confiar en mirar en las entrañas de un marco para determinar con qué puede salirse con la suya es un camino hacia una pesadilla de mantenimiento. Le recomiendo encarecidamente seguir la documentación y manejar correctamente los objetos desechables, le ahorrará dolor a largo plazo.
usuario poco entusiasta
2
@ijt, X2 le dice que use dos dígitos hexadecimales por byte. x2significa minúscula, X2es mayúscula
Mitch
38
public string Hash(byte [] temp)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {
        var hash = sha1.ComputeHash(temp);
        return Convert.ToBase64String(hash);
    }
}

EDITAR:

También puede especificar la codificación al convertir la matriz de bytes en una cadena de la siguiente manera:

return System.Text.Encoding.UTF8.GetString(hash);

o

return System.Text.Encoding.Unicode.GetString(hash);
John Gathogo
fuente
Escribí estos códigos antes pero no funcionó, no sé la razón
Merve Kaya
1
Si quieren una cadena hexadecimal, Base64 probablemente sea la elección incorrecta.
Joey
@Joey: Contra la respuesta dada por GrantThomas, el miembro indicó que necesitan devolver una cadena
John Gathogo
@MerveKaya: Quizás deberías explicar lo que quieres decir con "no funcionó". ¿Qué representa la matriz de bytes entrante? ¿Cómo determinó "SHA1Managed"? ¿La matriz de bytes entrante debería darle 0d71ee4472658cd5874c5578410a9d8611fc9aefcomo salida?
John Gathogo
El hash de bytes [] proviene de la prueba unitaria. En la pregunta, escribieron que el hash esperado es 0d71ee4472658cd5874c5578410a9d8611fc9aef. Viene de la prueba unitaria
Merve Kaya
15

Esto es con lo que fui. Para aquellos de ustedes que quieran optimizar, consulte https://stackoverflow.com/a/624379/991863 .

    public static string Hash(string stringToHash)
    {
        using (var sha1 = new SHA1Managed())
        {
            return BitConverter.ToString(sha1.ComputeHash(Encoding.UTF8.GetBytes(stringToHash)));
        }
    }
sky-dev
fuente
Tuve que usar BitConverter.ToString (sha1.ComputeHash (bytes)). Reemplazar ("-", "") ya que no quería que los guiones introducidos por BitConverter. ¡Después de eso funcionó como un encanto! ¡Gracias!
Sam
9

La forma más rápida es esta:

    public static string GetHash(string input)
    {
        return string.Join("", (new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(input))).Select(x => x.ToString("X2")).ToArray());
    }

Para salida de caracteres pequeños, utilice x2en reemplazo deX2

alireza amini
fuente
4
SHA1Managed implementa IDisposable, por lo que probablemente querrá deshacerse de él cuando haya terminado para liberar recursos.
rickythefox
8

Puede "calcular el valor de la matriz de bytes especificada" mediante ComputeHash:

var hash = sha1.ComputeHash(temp);

Si desea analizar el resultado en una representación de cadena, deberá formatear los bytes utilizando el {0:X2}especificador de formato.

Grant Thomas
fuente
4

Arrojaré mi sombrero aquí:

(como parte de una clase estática, ya que este fragmento son dos extensiones)

//hex encoding of the hash, in uppercase.
public static string Sha1Hash (this string str)
{
    byte[] data = UTF8Encoding.UTF8.GetBytes (str);
    data = data.Sha1Hash ();
    return BitConverter.ToString (data).Replace ("-", "");
}
// Do the actual hashing
public static byte[] Sha1Hash (this byte[] data)
{
    using (SHA1Managed sha1 = new SHA1Managed ()) {
    return sha1.ComputeHash (data);
}
oPless
fuente