Băm với Thuật toán SHA1 trong C #


84

Tôi muốn băm byte[]mảng đã cho bằng cách sử dụng SHA1Thuật toán với việc sử dụng SHA1Managed.
Hàm byte[]băm sẽ đến từ bài kiểm tra đơn vị.
Giá trị băm mong đợi là 0d71ee4472658cd5874c5578410a9d8611fc9aef(phân biệt chữ hoa chữ thường).

Làm thế nào tôi có thể đạt được điều này?

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

    }
}

1
Băm excpected của bạn là một giá trị thập lục phân, vì vậy nó không quan trọng nếu nó trường hợp ví dụ như nhạy cảmhex(e) == hex(E)
JAC

Câu trả lời:


170

Đối với những người muốn định dạng văn bản "tiêu chuẩn" của băm, bạn có thể sử dụng một cái gì đó như sau:

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

Điều này sẽ tạo ra một hàm băm như thế nào 0C2E99D0949684278C30B9369B82638E1CEAD415.

Hoặc đối với phiên bản chơi gôn mã:

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

Tôi làm phiền tôi rằng giải pháp này không loại bỏ được đối tượng SHA1Managed, vì nó được đánh dấu là Dùng một lần. Bài đăng này có thể hữu ích khi tối ưu hóa: stackoverflow.com/a/624379/991863
sky-dev

@ sky-dev, tôi thường đồng ý với IDisposable, nhưng một chuyến đi ngắn đến các nguồn tài liệu tham khảo cho thấy rằng không có gì thú vị xảy ra trong.Dispose()
Mitch

Vâng, tôi cũng đã xem xét việc triển khai Dispose. Nó sẽ chỉ tăng tốc độ GarbageCollection một chút. Nó có lẽ không phải là một vấn đề lớn trong kế hoạch lớn của mọi thứ.
sky-dev

21
@Mitch Nếu nó triển khai giao diện IDisposable thì những gì xảy ra trong nguồn tham chiếu sẽ không thành vấn đề. Nếu họ có bao giờ thay đổi nó vì bất kỳ lý do gì khiến cuộc gọi .Dispose () trở nên quan trọng, thì mã làm việc trước đây của bạn hiện đang gây ra sự cố. Chỉ dựa vào việc tìm hiểu kỹ trong ruột của một khuôn khổ để xác định những gì bạn có thể bỏ qua là một con đường dẫn đến một cơn ác mộng bảo trì. Tôi thực sự khuyên bạn nên làm theo tài liệu và xử lý chính xác các đồ vật dùng một lần, nó sẽ giúp bạn đỡ đau đớn về lâu dài.
không nhiệt tình

2
@ijt, X2 yêu cầu nó sử dụng hai chữ số thập lục phân trên mỗi byte. x2có nghĩa là chữ thường, X2là chữ hoa
Mitch

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

BIÊN TẬP:

Bạn cũng có thể chỉ định mã hóa khi chuyển đổi mảng byte thành chuỗi như sau:

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

hoặc là

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

Tôi đã viết những mã trước đây nhưng nó làm việc Tôi không biết lý do
Merve Kaya

1
Nếu họ muốn một chuỗi hex thì Base64 có lẽ là lựa chọn sai lầm.
Joey

@Joey: Chống lại câu trả lời được đưa ra bởi GrantThomas, thành viên chỉ ra rằng họ cần phải trả lại một chuỗi
John Gathogo

@MerveKaya: Có lẽ bạn nên giải thích ý bạn là "nó không hoạt động". Mảng byte đến đại diện cho điều gì? Làm cách nào để bạn xác định "SHA1Managed" - băm mảng byte đến sẽ cung cấp cho bạn 0d71ee4472658cd5874c5578410a9d8611fc9aeflàm đầu ra?
John Gathogo

Byte [] hash đến từ unit test. Trong câu hỏi, họ đã viết rằng hàm băm mong đợi là 0d71ee4472658cd5874c5578410a9d8611fc9aef. Nó xuất phát từ đơn vị kiểm tra
Merve Kaya

15

Đây là những gì tôi đã đi cùng. Đối với những người bạn muốn tối ưu hóa, hãy xem 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)));
        }
    }

Tôi đã phải sử dụng BitConverter.ToString (sha1.ComputeHash (byte)). Thay thế ("-", "") vì tôi không muốn có dấu gạch ngang do BitConverter giới thiệu. Sau đó nó hoạt động như một sự quyến rũ! Cảm ơn!
Sam

9

Cách nhanh nhất là:

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

Đối với đầu ra ký tự nhỏ, sử dụng x2thay thế choX2


4
SHA1Managed triển khai IDisposable, vì vậy bạn có thể muốn loại bỏ nó khi hoàn tất để giải phóng tài nguyên.
rickythefox

8

Bạn có thể "tính toán giá trị cho mảng byte được chỉ định" bằng cách sử dụng ComputeHash:

var hash = sha1.ComputeHash(temp);

Nếu bạn muốn phân tích kết quả trong biểu diễn chuỗi, thì bạn sẽ cần phải định dạng các byte bằng cách sử dụng công {0:X2}cụ định dạng.


4

Tôi sẽ ngả mũ ở đây:

(là một phần của lớp tĩnh, vì đoạn mã này là hai phần mở rộng)

//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);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.