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())
    {

    }
}

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

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

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

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


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.


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);
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.