Hitung hash MD5 dari string

131

Saya menggunakan kode C # berikut untuk menghitung hash MD5 dari sebuah string. Ini bekerja dengan baik dan menghasilkan string hex 32-karakter seperti ini: 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...

Apakah ada cara untuk menggunakan kode seperti ini untuk menghasilkan string hex 16-karakter (atau string 12-karakter)? String hex 32-karakter bagus tapi saya pikir itu akan membosankan bagi pelanggan untuk memasukkan kode!

Muhamad Jafarnejad
sumber
7
mengapa Anda membutuhkan pelanggan untuk memasukkan hex?
Dan Dinu
5
Saya pikir dia ingin membuat kunci serial
Thiago

Jawaban:

197

Sesuai MSDN

Buat 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();
    }
}
Anant Dabhi
sumber
5
Anda harus selalu mengatakan dari mana Anda mendapatkan kode jika Anda menyalin / menempel dari suatu tempat, jika tidak itu diklasifikasikan sebagai plagiarisme.
DavidG
1
Kelas MD5 mengimplementasikan IDisposable, ingatlah untuk membuang instance Anda. ;)
Paolo Iommarini
5
Secara umum Anda harus hash penyandian teks lossless, seperti UTF8.
Oliver Bock
5
@ PrashantPimpale MD5 adalah algoritme intisari. Anggap saja mengubah sapi menjadi steak.
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
Michael
sumber
13
Jawaban saya bukan untuk menunjukkan praktik terbaik. Itu disediakan dalam konteks bahwa OP telah membingkai pertanyaannya. Jika OP bertanya apa algoritma hashing yang paling tepat untuk digunakan, jawabannya akan berbeda (sesuai).
Michael
8
Saya menghargai suara turun untuk sesuatu yang diambil di luar konteks untuk utas yang berusia lebih dari dua tahun. ;)
Michael
Kenapa "mirip dengan format UNIX"? Apa itu tidak persis sama?
Igor Gatis
ini memberikan hasil yang berbeda dari checker MD5 online. atau hanya aku ??
bh_earth0
@ bh_earth0 tampaknya BitConvertertidak bekerja dengan cara yang sama di windows dan linux, lihat pertanyaan ini: stackoverflow.com/questions/11454004/…
eddyP23
10

Sedang mencoba untuk membuat representasi string hash MD5 menggunakan LINQ, namun, tidak ada jawaban yang solusi LINQ, oleh karena itu menambahkan ini ke hamparan solusi yang tersedia.

string result;
using (MD5 hash = MD5.Create())
{
    result = String.Join
    (
        "",
        from ba in hash.ComputeHash
        (
            Encoding.UTF8.GetBytes(observedText)
        ) 
        select ba.ToString("x2")
    );
}
craigdfrench
sumber
One-liner, dalam sintaksis metode:return string.Join( "", hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );
Marc.2377
... dalam hal ini, saya mengusulkan return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );sebagai gantinya. Ini sedikit lebih pendek, mungkin niat lebih jelas, dan berkinerja sedikit lebih cepat (<10% perf. Meningkat).
Marc.2377
9

Tergantung sepenuhnya pada apa yang ingin Anda capai. Secara teknis, Anda bisa mengambil 12 karakter pertama dari hasil hash MD5, tetapi spesifikasi MD5 adalah untuk menghasilkan karakter 32 karakter.

Mengurangi ukuran hash mengurangi keamanan, dan meningkatkan kemungkinan tabrakan dan sistem menjadi rusak.

Mungkin jika Anda memberi tahu kami lebih banyak tentang apa yang ingin Anda capai, kami mungkin dapat membantu lebih banyak.

KingCronus
sumber
+1 Ini adalah jawabannya, tetapi saya juga benar-benar mempertanyakan keamanannya.
lc.
Terima kasih atas jawaban anda. dan maaf tentang penjelasan saya yang buruk. Saya ingin menerbitkan aplikasi untuk windows, pengguna harus membeli lisensi untuk menggunakan aplikasi saya, jadi aplikasi saya meminta dua bidang: USERNAME: ..., dan KEY: .... Saya ingin hash the USERNAME dan buat KEY , maka pengguna harus memasukkan USERNAME dan KUNCI spesifik. masalah saya di sini adalah bahwa KUNCI harus 12-karakter, (Tapi dalam hash MD5, saya mendapatkan KUNCI 32-char). tolong bantu saya, saya sangat membutuhkannya.
Muhamad Jafarnejad
8

Anda dapat menggunakan Convert.ToBase64Stringuntuk mengonversi 16 byte output MD5 ke string ~ 24 char. Sedikit lebih baik tanpa mengurangi keamanan. ( j9JIbSY8HuT89/pwdC8jlw==sebagai contoh)

LB
sumber
2
Solusi yang bagus, tapi saya ragu dia akan OP ingin peka huruf besar-kecil dan dengan karakter khusus ...
KingCronus
5

Mendukung aliran string dan file.

contoh

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);
            }
        }
Berpikir Besar
sumber
4

Saya kira lebih baik menggunakan pengkodean UTF-8 dalam string 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();
    }
}
Tomas Kubes
sumber
3

Hash MD5 adalah 128 bit, jadi Anda tidak dapat merepresentasikannya dalam hex dengan kurang dari 32 karakter ...

Thomas Levesque
sumber
Ok, saya pasti melewatkan sesuatu di sini. Bagaimana?
lc.
@ lc., maaf, ada kesalahan ketik dalam jawaban saya, saya telah menulis "bisa" bukannya "tidak bisa" ...
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();
Kristian Jay
sumber
3

Alternatif jawaban yang ada untuk .NET Core 2.1 dan yang lebih cepat:

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

Anda dapat mengoptimalkannya lebih banyak lagi jika Anda yakin bahwa string Anda cukup kecil dan ganti pengodean. DapatkanBytes dengan intro GetBytes (ReadOnlySpan chars, Span byte) alternatif yang tidak aman.

Tomas Kubes
sumber
3

Solusi ini membutuhkan c # 8 dan memanfaatkan Span<T>. Catatan, Anda masih perlu menelepon .Replace("-", string.Empty).ToLowerInvariant()untuk memformat hasilnya jika perlu.

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());
}
Brad M
sumber
0
StringBuilder sb= new StringBuilder();
for (int i = 0; i < tmpHash.Length; i++)
{
   sb.Append(tmpHash[i].ToString("x2"));
}
Suhrob Samiev
sumber
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);

            }
KhaledDev
sumber
0

Saya ingin menawarkan alternatif yang tampaknya berkinerja setidaknya 10% lebih cepat daripada jawaban craigdfrench dalam pengujian saya (.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();
    }
}

Jika Anda lebih suka memiliki using System.Runtime.Remoting.Metadata.W3cXsd2001;di atas, badan metode dapat dibuat lebih mudah dibaca satu-liner:

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

Cukup jelas, tetapi untuk kelengkapan, dalam konteks OP itu akan digunakan sebagai:

sSourceData = "MySourceData";
tmpHash = GetMD5Hash(sSourceData);
Marc.2377
sumber
0

Idk apa saja tentang string hex 16 karakter ....

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

Tapi ini milik saya untuk membuat hash MD5 dalam satu baris.

string hash = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes("THIS STRING TO MD5"))).Replace("-","");
IntegratedHen
sumber