Chuỗi băm trong c #


91

Tôi gặp sự cố khi cố gắng nhập chuỗi băm c#.

Tôi đã thử một vài trang web, nhưng hầu hết chúng đều đang sử dụng tệp để lấy băm. Những thứ khác dành cho chuỗi hơi quá phức tạp. Tôi đã tìm thấy các ví dụ về xác thực Windows cho web như sau:

FormsAuthentication.HashPasswordForStoringInConfigFile(tbxPassword.Text.Trim(), "md5")

Tôi cần sử dụng hàm băm để tạo một chuỗi chứa tên tệp an toàn hơn. Làm thế nào tôi có thể làm điều đó?

Thí dụ:

string file  = "username";
string hash = ??????(username); 

Tôi có nên sử dụng một thuật toán băm khác không phải "md5" không?

Câu trả lời:


183
using System.Security.Cryptography;

public static byte[] GetHash(string inputString)
{
    using (HashAlgorithm algorithm = SHA256.Create())
        return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString));
}

public static string GetHashString(string inputString)
{
    StringBuilder sb = new StringBuilder();
    foreach (byte b in GetHash(inputString))
        sb.Append(b.ToString("X2"));

    return sb.ToString();
}

Ghi chú bổ sung

  • Vì MD5 và SHA1 là các thuật toán lỗi thời và không an toàn , giải pháp này sử dụng SHA256. Ngoài ra, bạn có thể sử dụng BCrypt hoặc Scrypt như được chỉ ra trong nhận xét.
  • Ngoài ra, hãy cân nhắc " ướp muối " các hàm băm của bạn và sử dụng các thuật toán mật mã đã được chứng minh, như được chỉ ra trong các nhận xét.

46
KHÔNG SỬ DỤNG MD5 HOẶC SHA1 , chúng là các thuật toán lỗi thời và không an toàn. Sử dụng SHA256 ít nhất hoặc thậm chí tốt hơn sử dụng BCrypt hoặc Scrypt.
Muhammad Rehan Saeed

1
Xem ví dụ này về việc sử dụng SCrypt: stackoverflow.com/questions/20042977/…
Muhammad Rehan Saeed

6
@Muh Nó có thể dễ dàng được sử dụng cho tổng kiểm tra, vì nó nhanh hơn nhiều so với SHA512. Nhưng quả thực để lưu trữ Mật khẩu thì không nên, đúng vậy.
LuckyLikey

5
Điều này b.ToString("X2")có nghĩa là gì?
Bilal Fazlani


60

Cách nhanh nhất, để lấy một chuỗi băm cho mục đích lưu trữ mật khẩu, là một đoạn mã sau:

    internal static string GetStringSha256Hash(string text)
    {
        if (String.IsNullOrEmpty(text))
            return String.Empty;

        using (var sha = new System.Security.Cryptography.SHA256Managed())
        {
            byte[] textData = System.Text.Encoding.UTF8.GetBytes(text);
            byte[] hash = sha.ComputeHash(textData);
            return BitConverter.ToString(hash).Replace("-", String.Empty);
        }
    }

Nhận xét:

  • nếu phương thức được gọi thường xuyên, việc tạo shabiến phải được cấu trúc lại thành một trường lớp;
  • đầu ra được trình bày dưới dạng chuỗi hex được mã hóa;

SHA1Managedlớp học không tốn kém lắm. nó tiêu thụ khoảng 130 byte và khởi tạo chúng thành một số giá trị tĩnh, nhưng đó là tất cả. vì vậy sẽ không có vấn đề về hiệu suất trong hầu hết các trường hợp.
Earth Engine vào

1
Cũng SHA1ManagedIDisposablevà do đó yêu cầu để quấn sử dụng của nó thành một usingkhối.
Earth Engine vào

DisposePhương pháp mục đích là xóa bộ đệm bên trong. Nếu không làm như vậy sẽ có nguy cơ bị tấn công bộ nhớ.
Earth Engine vào

3
@MuhammadRehanSaeed khi tôi nói SHA1Managedlà không tốn kém, ý tôi là việc tạo ra nó là không. Ngoài ra, một thuật toán băm không cần thiết phải tốn kém. Nó chỉ phải (cực kỳ) tốn kém khi bạn muốn tìm thấy một vụ va chạm.
Earth Engine

1
@King_Fisher - không thể! Hash là một chức năng một chiều, thông tin bị mất. Nếu bạn cần giải mã, bạn cần sử dụng phương pháp mã hóa không băm. BTW, mã hóa mật khẩu là một việc làm không tốt.
andrew.fox

8

Tôi không thực sự hiểu toàn bộ phạm vi câu hỏi của bạn, nhưng nếu tất cả những gì bạn cần là một hàm băm của chuỗi, thì rất dễ dàng đạt được điều đó.

Chỉ cần sử dụng phương thức GetHashCode.

Như thế này:

string hash = username.GetHashCode();

1
Vâng, đó là những gì đang tìm kiếm. Nhưng nó là sai lầm lớn. Hiển thị ghi như int hash = "username" .GetHasCode ();
Edy Cu

3
Tại sao bạn lại đặt tên người dùng trong dấu ngoặc kép? Điều đó sẽ nhận được băm của từ 'tên người dùng' và bây giờ là những gì trong biến tên người dùng.
Cyril Gupta,

14
không lưu trữ các giá trị từ GetHashCode, nó là khác nhau cho 32x và 64x
Slava

12
Đây là một cách xấu để tạo mật khẩu băm. Với GetHashCode (), bạn không thể giả định rằng cùng một số sẽ được tạo trên máy tính khác nhau. Sử dụng phương pháp SHA1 băm hoặc một cái gì đó (tôi sẽ gửi một ví dụ sau)
andrew.fox

2
Cần lưu ý rằng đó GetHashCodekhông phải là một thuật toán băm mật mã an toàn. Sử dụng SHA256 ít nhất hoặc thậm chí tốt hơn sử dụng BCrypt hoặc Scrypt cho một thuật toán an toàn.
Muhammad Rehan Saeed

5

Tôi nghĩ những gì bạn đang tìm kiếm không phải là băm mà là mã hóa. Với băm, bạn sẽ không thể lấy tên tệp gốc từ biến "băm". Với mã hóa, bạn có thể và nó an toàn.

Xem AES trong ASP.NET với VB.NET để biết thêm thông tin về mã hóa trong .NET.


vâng, tôi nghĩ là mã hóa, nhưng tôi chỉ muốn so sánh kết quả băm. Sau khi chuyển hướng trang.
Edy Cu

Bạn muốn so sánh tên tệp đã băm với cái gì?
Pieter van Ginkel 21/10/10

1
//Secure & Encrypte Data
    public static string HashSHA1(string value)
    {
        var sha1 = SHA1.Create();
        var inputBytes = Encoding.ASCII.GetBytes(value);
        var hash = sha1.ComputeHash(inputBytes);
        var sb = new StringBuilder();
        for (var i = 0; i < hash.Length; i++)
        {
            sb.Append(hash[i].ToString("X2"));
        }
        return sb.ToString();
    }

3
KHÔNG SỬ DỤNG SHA1 từ liên kết này, SHA1 là một thuật toán lỗi thời và không an toàn. Sử dụng SHA256 ít nhất hoặc thậm chí tốt hơn sử dụng BCrypt hoặc Scrypt.
Muhammad Rehan Saeed

Xem ví dụ này về việc sử dụng SCrypt: stackoverflow.com/questions/20042977/…
Muhammad Rehan Saeed

1

Nếu hiệu suất không phải là mối quan tâm lớn, bạn cũng có thể sử dụng bất kỳ phương pháp nào sau đây:
(Trong trường hợp bạn muốn chuỗi băm ở dạng chữ hoa, hãy thay thế "x2"bằng "X2".)

public static string SHA256ToString(string s) 
{
    using (var alg = SHA256.Create())
        return string.Join(null, alg.ComputeHash(Encoding.UTF8.GetBytes(s)).Select(x => x.ToString("x2")));
}

hoặc là:

public static string SHA256ToString(string s)
{            
    using (var alg = SHA256.Create())
        return alg.ComputeHash(Encoding.UTF8.GetBytes(s)).Aggregate(new StringBuilder(), (sb, x) => sb.Append(x.ToString("x2"))).ToString();
}

0

Con đường ngắn nhất và nhanh nhất từ ​​trước đến nay. Chỉ 1 dòng!

    public static string StringSha256Hash(string text) =>
        string.IsNullOrEmpty(text) ? string.Empty : BitConverter.ToString(new System.Security.Cryptography.SHA256Managed().ComputeHash(System.Text.Encoding.UTF8.GetBytes(text))).Replace("-", string.Empty);
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.