Хеширование с помощью алгоритма SHA1 в C #


86

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

Как я могу этого добиться?

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

    }
}

1
Ваш ожидаемый хеш - это шестнадцатеричное значение, поэтому не имеет значения, чувствителен ли он к регистру, напримерhex(e) == hex(E)
jAC

Ответы:


173

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

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, потому что он помечен как Disposable. Этот пост может быть полезен при оптимизации: stackoverflow.com/a/624379/991863
sky-dev

@ sky-dev, я обычно согласен с этим IDisposable, но беглый переход к справочнику показывает, что ничего интересного не происходит в.Dispose()
Митч

Да, я тоже посмотрел на реализацию Dispose. Это просто немного ускорит GarbageCollection. Вероятно, это не имеет большого значения в общем плане вещей.
sky-dev

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

2
@ijt, X2 указывает ему использовать две шестнадцатеричные цифры на байт. x2означает строчные, X2это прописные
Mitch

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

Я писал эти коды раньше, но это не сработало, я не знаю причины
Мерв Кайя

1
Если им нужна шестнадцатеричная строка, то Base64, вероятно, будет неправильным выбором.
Joey

@Joey: В ответ на ответ GrantThomas участник указал, что им нужно вернуть строку
John Gathogo

@MerveKaya: Возможно, тебе стоит объяснить, что ты имеешь в виду, говоря «это не сработало». Что представляет собой массив входящих байтов? Как вы определили, что "SHA1Managed" - хеширование входящего байтового массива должно давать вам 0d71ee4472658cd5874c5578410a9d8611fc9aefна выходе?
John Gathogo

Хеш Byte [] получен из модульного теста. В вопросе написали, что ожидаемый хеш - 0d71ee4472658cd5874c5578410a9d8611fc9aef. Это взято из модульного теста
Мерве Кая

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 (bytes)). Replace ("-", ""), так как мне не нужны тире, вводимые 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вместо ofX2


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.