Haszowanie z algorytmem SHA1 w C #

86

Chcę zaszyfrować podaną byte[]tablicę przy użyciu SHA1algorytmu z użyciem SHA1Managed. Hash będzie pochodzić z testów jednostkowych. Oczekiwany skrót to (rozróżniana jest wielkość liter).
byte[]
0d71ee4472658cd5874c5578410a9d8611fc9aef

Jak mogę to osiągnąć?

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

    }
}
Merve Kaya
źródło
1
Twój oczekiwany hash jest wartością szesnastkową, więc nie ma znaczenia, czy jest rozróżniana hex(e) == hex(E)
wielkość

Odpowiedzi:

173

Dla tych, którzy chcą „standardowego” formatowania tekstu skrótu, możesz użyć czegoś podobnego do następującego:

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();
    }
}

Spowoduje to powstanie haszyszu 0C2E99D0949684278C30B9369B82638E1CEAD415.

Lub w przypadku wersji z kodem golfowym:

static string Hash(string input)
{
    var hash = new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(input));
    return string.Concat(hash.Select(b => b.ToString("x2")));
}
Mitch
źródło
Martwi mnie, że to rozwiązanie nie usuwa obiektu SHA1Managed, ponieważ jest oznaczony jako jednorazowy. Ten post może być przydatny podczas optymalizacji: stackoverflow.com/a/624379/991863
sky-dev
@ sky-dev, zwykle się z tym zgadzam IDisposable, ale krótka wycieczka do źródła referencyjnego pokazuje, że nic ciekawego się nie dzieje.Dispose()
Mitch
Tak, przyjrzałem się również implementacji Dispose. To tylko odrobinę przyspieszyło GarbageCollection. Prawdopodobnie nie jest to wielka sprawa w wielkim planie rzeczy.
sky-dev
21
@Mitch Jeśli implementuje interfejs IDisposable, to co dzieje się w źródle odniesienia nie powinno mieć znaczenia. Jeśli kiedykolwiek zmienią to z jakiegokolwiek powodu, tak że wywołanie .Dispose () stanie się ważne, twój poprzednio działający kod powoduje teraz problem. Poleganie na zajrzeniu do wnętrza struktury w celu ustalenia, z czym można uciec, jest drogą do koszmaru związanego z konserwacją. Gorąco radzę postępować zgodnie z dokumentacją i prawidłowo obchodzić się z przedmiotami jednorazowego użytku, na dłuższą metę zaoszczędzi to bólu.
unenthusiasticuser
2
@ijt, X2 mówi mu, aby używał dwóch cyfr szesnastkowych na bajt. x2oznacza małe litery, X2jest duże
Mitch
38
public string Hash(byte [] temp)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {
        var hash = sha1.ComputeHash(temp);
        return Convert.ToBase64String(hash);
    }
}

EDYTOWAĆ:

Możesz również określić kodowanie podczas konwersji tablicy bajtów na ciąg w następujący sposób:

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

lub

return System.Text.Encoding.Unicode.GetString(hash);
John Gathogo
źródło
Napisałem te kody wcześniej, ale nie zadziałały, nie znam powodu
Merve Kaya
1
Jeśli chcą ciągu szesnastkowego, prawdopodobnie Base64 jest złym wyborem.
Joey,
@Joey: Wbrew odpowiedzi udzielonej przez GrantThomas, członek wskazał, że musi zwrócić ciąg znaków
John Gathogo
@MerveKaya: Może powinieneś wyjaśnić, co masz na myśli mówiąc „to nie zadziałało”. Co reprezentuje przychodząca tablica bajtów? Jak ustaliłeś, że "SHA1Managed" -hashowanie przychodzącej tablicy bajtów powinno dać ci 0d71ee4472658cd5874c5578410a9d8611fc9aefwynik?
John Gathogo,
Skrót bajtu [] pochodzi z testu jednostkowego. W pytaniu napisali, że oczekiwany hash to 0d71ee4472658cd5874c5578410a9d8611fc9aef. Pochodzi z testu jednostkowego
Merve Kaya,
15

To jest to, z czym poszedłem. Dla tych z Was, którzy chcą zoptymalizować, sprawdź 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
źródło
Musiałem użyć BitConverter.ToString (sha1.ComputeHash (bajty)). Zastąp ("-", ""), ponieważ nie chciałem, aby myślniki wprowadzane przez BitConverter. Potem działało jak urok! Dzięki!
Sam,
9

Najszybszy sposób to:

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

W przypadku małych znaków należy użyć x2zamiastX2

alireza amini
źródło
4
SHA1Managed implementuje IDisposable, więc prawdopodobnie chciałbyś go pozbyć, gdy skończysz z nim, aby zwolnić zasoby.
rickythefox
8

Możesz "obliczyć wartość dla określonej tablicy bajtów" używając ComputeHash:

var hash = sha1.ComputeHash(temp);

Jeśli chcesz przeanalizować wynik w postaci ciągu, musisz sformatować bajty przy użyciu specyfikatora {0:X2}formatu.

Grant Thomas
źródło
4

Wrzucę tutaj swój kapelusz:

(jako część klasy statycznej, ponieważ ten fragment to dwa rozszerzenia)

//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);
}
bez
źródło