Tính toán băm MD5 từ một chuỗi


131

Tôi sử dụng mã C # sau để tính băm MD5 từ một chuỗi. Nó hoạt động tốt và tạo ra chuỗi hex 32 ký tự như thế này: 900150983cd24fb0d6963f7d28e17f72

string sSourceData;
byte[] tmpSource;
byte[] tmpHash;
sSourceData = "MySourceData";

//Create a byte array from source data.
tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);

// and then convert tmpHash to string...

Có cách nào để sử dụng mã như thế này để tạo chuỗi hex 16 ký tự (hoặc chuỗi 12 ký tự) không? Chuỗi hex gồm 32 ký tự là tốt nhưng tôi nghĩ rằng sẽ rất nhàm chán khi khách hàng nhập mã!


7
Tại sao bạn cần khách hàng nhập hex?
Dan Dinu

5
Tôi nghĩ rằng anh ấy muốn tạo một khóa nối tiếp
Thiago

Câu trả lời:


197

Theo MSDN

Tạo MD5:

public static string CreateMD5(string input)
{
    // Use input string to calculate MD5 hash
    using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
    {
        byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
        byte[] hashBytes = md5.ComputeHash(inputBytes);

        // Convert the byte array to hexadecimal string
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hashBytes.Length; i++)
        {
            sb.Append(hashBytes[i].ToString("X2"));
        }
        return sb.ToString();
    }
}


5
Bạn phải luôn luôn nói bạn lấy mã từ đâu nếu bạn sao chép / dán từ đâu đó, nếu không nó được phân loại là đạo văn.
DavidG

1
Lớp MD5 triển khai IDis Dùng một lần, hãy nhớ loại bỏ cá thể của bạn. ;)
Paolo Iommarini

5
Nói chung, bạn nên băm một mã hóa văn bản lossless, như UTF8.
Oliver Bock

5
@PrashantPimpale MD5 là một thuật toán tiêu hóa. Hãy nghĩ về nó như chuyển đổi một con bò thành bít tết.
Anant Dabhi

95
// given, a password in a string
string password = @"1234abcd";

// byte array representation of that string
byte[] encodedPassword = new UTF8Encoding().GetBytes(password);

// need MD5 to calculate the hash
byte[] hash = ((HashAlgorithm) CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedPassword);

// string representation (similar to UNIX format)
string encoded = BitConverter.ToString(hash)
   // without dashes
   .Replace("-", string.Empty)
   // make lowercase
   .ToLower();

// encoded contains the hash you want

13
Câu trả lời của tôi không phải là để biểu thị thực hành tốt nhất. Nó được cung cấp trong bối cảnh mà OP đã đóng khung câu hỏi của anh ấy. Nếu OP đã hỏi thuật toán băm thích hợp nhất để sử dụng là gì, câu trả lời sẽ khác (theo đó).
Michael

8
Tôi đánh giá cao việc bỏ phiếu cho một cái gì đó được đưa ra khỏi bối cảnh cho một chủ đề đã hơn hai năm tuổi. ;)
Michael

Tại sao "tương tự định dạng UNIX"? Những gì nó không hoàn toàn giống nhau?
Igor Gatis

điều này cho kết quả khác nhau từ trình kiểm tra md5 trực tuyến. hay la chỉ Minh tôi??
bh_earth0

@ bh_earth0 có vẻ như BitConverterkhông hoạt động theo cùng một kiểu trên windows và linux, hãy xem câu hỏi này: stackoverflow.com/questions/11454004/
Lỗi

10

Đã cố gắng tạo một chuỗi đại diện cho hàm băm MD5 bằng LINQ, tuy nhiên, không có câu trả lời nào là giải pháp LINQ, do đó thêm điều này vào smorgasbord của các giải pháp khả dụng.

string result;
using (MD5 hash = MD5.Create())
{
    result = String.Join
    (
        "",
        from ba in hash.ComputeHash
        (
            Encoding.UTF8.GetBytes(observedText)
        ) 
        select ba.ToString("x2")
    );
}

Cú pháp một lớp, theo phương thức:return string.Join( "", hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );
Marc.2377

... Trong trường hợp đó, tôi đề xuất return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );thay thế. Đó là một chút ngắn hơn, có thể rõ ràng hơn ý định và thực hiện nhanh hơn một chút (tăng 10% hoàn hảo.).
Marc.2377

9

Phụ thuộc hoàn toàn vào những gì bạn đang cố gắng để đạt được. Về mặt kỹ thuật, bạn chỉ có thể lấy 12 ký tự đầu tiên từ kết quả của hàm băm MD5, nhưng đặc điểm kỹ thuật của MD5 là tạo ra một ký tự 32 char.

Giảm kích thước của hàm băm làm giảm tính bảo mật và tăng khả năng va chạm và hệ thống bị phá vỡ.

Có lẽ nếu bạn cho chúng tôi biết thêm về những gì bạn đang cố gắng đạt được, chúng tôi có thể hỗ trợ thêm.


+1 Đây là câu trả lời, nhưng tôi cũng vậy, thực sự đặt câu hỏi về tính bảo mật của nó.
lc.

cảm ơn câu trả lời của bạn. và xin lỗi về lời giải thích tồi tệ của tôi. Tôi muốn xuất bản một ứng dụng cho windows, người dùng nên mua giấy phép sử dụng ứng dụng của mình, vì vậy ứng dụng của tôi yêu cầu hai trường: USERNAME: ..., và KEY: .... Tôi muốn băm USERNAME và tạo KEY , sau đó người dùng nên nhập USERNAME và KEY cụ thể. Vấn đề của tôi ở đây là KEY phải có 12 ký tự, (Nhưng trong hàm băm MD5, tôi nhận được KEY 32 char). Xin hãy giúp tôi, tôi thực sự cần nó.
Muhamad Jafarnejad

8

Bạn có thể sử dụng Convert.ToBase64Stringđể chuyển đổi đầu ra 16 byte của MD5 thành chuỗi ~ 24 char. Tốt hơn một chút mà không làm giảm an ninh. ( j9JIbSY8HuT89/pwdC8jlw==ví dụ của bạn)


2
Một cách giải quyết tốt, nhưng tôi nghi ngờ anh ấy OP sẽ muốn có trường hợp nhạy cảm và với các ký tự đặc biệt ...
KingCronus

5

Hỗ trợ chuỗi và luồng tập tin.

ví dụ

string hashString = EasyMD5.Hash("My String");

string hashFile = EasyMD5.Hash(System.IO.File.OpenRead("myFile.txt"));

-

   class EasyMD5
        {
            private static string GetMd5Hash(byte[] data)
            {
                StringBuilder sBuilder = new StringBuilder();
                for (int i = 0; i < data.Length; i++)
                    sBuilder.Append(data[i].ToString("x2"));
                return sBuilder.ToString();
            }

            private static bool VerifyMd5Hash(byte[] data, string hash)
            {
                return 0 == StringComparer.OrdinalIgnoreCase.Compare(GetMd5Hash(data), hash);
            }

            public static string Hash(string data)
            {
                using (var md5 = MD5.Create())
                    return GetMd5Hash(md5.ComputeHash(Encoding.UTF8.GetBytes(data)));
            }
            public static string Hash(FileStream data)
            {
                using (var md5 = MD5.Create())
                    return GetMd5Hash(md5.ComputeHash(data));
            }

            public static bool Verify(string data, string hash)
            {
                using (var md5 = MD5.Create())
                    return VerifyMd5Hash(md5.ComputeHash(Encoding.UTF8.GetBytes(data)), hash);
            }

            public static bool Verify(FileStream data, string hash)
            {
                using (var md5 = MD5.Create())
                    return VerifyMd5Hash(md5.ComputeHash(data), hash);
            }
        }

4

Tôi cho rằng tốt hơn là sử dụng mã hóa UTF-8 trong chuỗi MD5.

public static string MD5(this string s)
{
    using (var provider = System.Security.Cryptography.MD5.Create())
    {
        StringBuilder builder = new StringBuilder();                           

        foreach (byte b in provider.ComputeHash(Encoding.UTF8.GetBytes(s)))
            builder.Append(b.ToString("x2").ToLower());

        return builder.ToString();
    }
}

3

Hàm băm MD5 là 128 bit, vì vậy bạn không thể biểu thị nó dưới dạng hex với ít hơn 32 ký tự ...


Ok, tôi phải thiếu một cái gì đó ở đây. Làm sao?
lc.

@lc., xin lỗi, có một lỗi đánh máy trong câu trả lời của tôi, tôi đã viết "có thể" thay vì "không thể" ...
Thomas Levesque

3
System.Text.StringBuilder hash = new System.Text.StringBuilder();
        System.Security.Cryptography.MD5CryptoServiceProvider md5provider = new System.Security.Cryptography.MD5CryptoServiceProvider();
        byte[] bytes = md5provider.ComputeHash(new System.Text.UTF8Encoding().GetBytes(YourEntryString));

        for (int i = 0; i < bytes.Length; i++)
        {
            hash.Append(bytes[i].ToString("x2")); //lowerCase; X2 if uppercase desired
        }
        return hash.ToString();

3

Một thay thế nhanh hơn cho câu trả lời hiện có cho .NET Core 2.1 trở lên:

public static string CreateMD5(string s)
{
    using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
    {
        var encoding = Encoding.ASCII;
        var data = encoding.GetBytes(s);

        Span<byte> hashBytes = stackalloc byte[16];
        md5.TryComputeHash(data, hashBytes, out int written);
        if(written != hashBytes.Length)
            throw new OverflowException();


        Span<char> stringBuffer = stackalloc char[32];
        for (int i = 0; i < hashBytes.Length; i++)
        {
            hashBytes[i].TryFormat(stringBuffer.Slice(2 * i), out _, "x2");
        }
        return new string(stringBuffer);
    }
}

Bạn có thể tối ưu hóa nó nhiều hơn nữa nếu bạn chắc chắn rằng chuỗi của bạn đủ nhỏ và thay thế mã hóa.GetBytes bằng cách không an toàn int GetBytes (ký tự ReadOnlySpan, byte Span).


3

Giải pháp này đòi hỏi c # 8 và tận dụng Span<T>. Lưu ý, bạn vẫn sẽ cần gọi .Replace("-", string.Empty).ToLowerInvariant()để định dạng kết quả nếu cần thiết.

public static string CreateMD5(ReadOnlySpan<char> input)
{
    var encoding = System.Text.Encoding.UTF8;
    var inputByteCount = encoding.GetByteCount(input);
    using var md5 = System.Security.Cryptography.MD5.Create();

    Span<byte> bytes = inputByteCount < 1024
        ? stackalloc byte[inputByteCount]
        : new byte[inputByteCount];
    Span<byte> destination = stackalloc byte[md5.HashSize / 8];

    encoding.GetBytes(input, bytes);

    // checking the result is not required because this only returns false if "(destination.Length < HashSizeValue/8)", which is never true in this case
    md5.TryComputeHash(bytes, destination, out int _bytesWritten);

    return BitConverter.ToString(destination.ToArray());
}

0
StringBuilder sb= new StringBuilder();
for (int i = 0; i < tmpHash.Length; i++)
{
   sb.Append(tmpHash[i].ToString("x2"));
}

0

https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.md5?view=netframework-4.7.2

using System;
using System.Security.Cryptography;
using System.Text;

    static string GetMd5Hash(string input)
            {
                using (MD5 md5Hash = MD5.Create())
                {

                    // Convert the input string to a byte array and compute the hash.
                    byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

                    // Create a new Stringbuilder to collect the bytes
                    // and create a string.
                    StringBuilder sBuilder = new StringBuilder();

                    // Loop through each byte of the hashed data 
                    // and format each one as a hexadecimal string.
                    for (int i = 0; i < data.Length; i++)
                    {
                        sBuilder.Append(data[i].ToString("x2"));
                    }

                    // Return the hexadecimal string.
                    return sBuilder.ToString();
                }
            }

            // Verify a hash against a string.
            static bool VerifyMd5Hash(string input, string hash)
            {
                // Hash the input.
                string hashOfInput = GetMd5Hash(input);

                // Create a StringComparer an compare the hashes.
                StringComparer comparer = StringComparer.OrdinalIgnoreCase;

                return 0 == comparer.Compare(hashOfInput, hash);

            }

0

Tôi muốn cung cấp một giải pháp thay thế dường như thực hiện nhanh hơn ít nhất 10% so với câu trả lời của craigdfbler trong các thử nghiệm của tôi (.NET 4.7.2):

public static string GetMD5Hash(string text)
{
    using ( var md5 = MD5.Create() )
    {
        byte[] computedHash = md5.ComputeHash( Encoding.UTF8.GetBytes(text) );
        return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString();
    }
}

Nếu bạn muốn có using System.Runtime.Remoting.Metadata.W3cXsd2001;ở trên cùng, phần thân phương thức có thể được đọc dễ dàng hơn để đọc một lớp lót:

using ( var md5 = MD5.Create() )
{
    return new SoapHexBinary( md5.ComputeHash( Encoding.UTF8.GetBytes(text) ) ).ToString();
}

Rõ ràng là đủ, nhưng để hoàn thiện, trong bối cảnh của OP, nó sẽ được sử dụng như:

sSourceData = "MySourceData";
tmpHash = GetMD5Hash(sSourceData);

0

Idk bất cứ điều gì về chuỗi hex 16 ký tự ....

using System;
using System.Security.Cryptography;
using System.Text;

Nhưng đây là của tôi để tạo băm MD5 trong một dòng.

string hash = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes("THIS STRING TO MD5"))).Replace("-","");
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.