Хешування за допомогою алгоритму SHA1 в C #


84

Я хочу хеш byte[]масиву з використанням SHA1алгоритму з використанням SHA1Managed. Хеш буде надходити з модульного тестування. Очікуваний хеш (чутливий до регістру).
byte[]
0d71ee4472658cd5874c5578410a9d8611fc9aef

Як я можу цього досягти?

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

    }
}

1
Ваш excpected хеш шістнадцяткове значення, так що це не має значення , якщо справа це відчутно , наприкладhex(e) == hex(E)
JAC

Відповіді:


170

Для тих, хто хоче "стандартне" форматування тексту хешу, ви можете використовувати щось на зразок наступного:

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

Це призведе до подібного хешу 0C2E99D0949684278C30B9369B82638E1CEAD415.

Або для кодової версії гольфу:

static string Hash(string input)
{
    var hash = new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(input));
    return string.Concat(hash.Select(b => b.ToString("x2")));
}

Мене турбує те, що це рішення не розпоряджається об’єктом SHA1Managed, оскільки воно позначене як Одноразове. Цей допис може стати в нагоді при оптимізації: stackoverflow.com/a/624379/991863
sky-dev

@ sky-dev, я зазвичай з цим погоджуюсь IDisposable, але швидка поїздка до джерела показує, що нічого цікавого не відбувається в.Dispose()
Мітч

Так, я також подивився реалізацію Dispose. Це просто пришвидшило б GarbageCollection. Можливо, це не є великою проблемою у великій схемі речей.
sky-dev

21
@Mitch Якщо він реалізує інтерфейс IDisposable, то те, що відбувається в джерелі посилань, не повинно мати значення. Якщо вони коли-небудь змінять його з будь-якої причини, такої, що виклик .Dispose () стане важливим, ваш раніше працюючий код зараз викликає проблему. Покладатись на заглиблення в надра каркасу, щоб визначити, з чим можна врятуватися - це шлях до кошмару технічного обслуговування. Я настійно рекомендую слідувати документації та правильно поводитися з одноразовими предметами, це позбавить вас від болю в довгостроковій перспективі.
без ентузіазму користувач

2
@ijt, X2 каже йому використовувати дві шістнадцяткові цифри на байт. x2означає малу літеру, X2є велику
Мітч

38
public string Hash(byte [] temp)
{
    using (SHA1Managed sha1 = new SHA1Managed())
    {
        var hash = sha1.ComputeHash(temp);
        return Convert.ToBase64String(hash);
    }
}

РЕДАГУВАТИ:

Ви також можете вказати кодування під час перетворення масиву байтів у рядок наступним чином:

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

або

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

Я писав ці коди раніше, але це не спрацювало, я не знаю причину
Merve Kaya

1
Якщо вони хочуть шістнадцятковий рядок, то Base64, мабуть, неправильний вибір.
Joey

@Joey: Проти відповіді, наданої GrantThomas, учасник вказав, що їм потрібно повернути рядок
John Gathogo

@MerveKaya: Можливо, вам слід пояснити, що ви маєте на увазі під словом "це не спрацювало". Що представляє вхідний байтовий масив? Як ви визначили "SHA1Managed" - хешування вхідного байтового масиву повинно дати вам 0d71ee4472658cd5874c5578410a9d8611fc9aefрезультат?
Джон Гатого

Хеш байтів [] походить від модульного тесту. У запитанні вони написали, що очікуваний хеш - 0d71ee4472658cd5874c5578410a9d8611fc9aef. Це відбувається з одиничного тесту
Merve Kaya

15

Це те, з чим я пішов. Для тих, хто хоче оптимізувати, перегляньте 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)));
        }
    }

Мені довелося використовувати BitConverter.ToString (sha1.ComputeHash (байти)). Замінити ("-", ""), оскільки я не хотів, щоб тире вводило BitConverter. Після цього це спрацювало як шарм! Дякую!
Сем

9

Це найшвидший спосіб:

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

Для виведення малих символів використовуйте x2замістьX2


4
SHA1Managed реалізує IDisposable, тому ви, мабуть, захочете розпорядитися ним, коли закінчите з ним, щоб звільнити ресурси.
rickythefox

8

Ви можете "обчислити значення для вказаного байтового масиву", використовуючи ComputeHash:

var hash = sha1.ComputeHash(temp);

Якщо ви хочете проаналізувати результат у рядковому поданні, то вам потрібно буде відформатувати байти за допомогою {0:X2}специфікатора формату.


4

Я кину сюди капелюх:

(як частина статичного класу, оскільки цей фрагмент - це два розширення)

//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);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.