Обчисліть хеш MD5 з рядка


131

Я використовую наступний код C # для обчислення хеша MD5 з рядка. Він добре працює і генерує 32-символьну шістнадцяткову рядок, як це: 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...

Чи є спосіб використовувати такий код, щоб створити шістнадцяткову шістнадцяткову рядок (або 12-символьну рядок)? Шістнадцятковий шістнадцятковий рядок хороший, але я думаю, що клієнту буде нудно вводити код!


7
навіщо вам потрібен клієнт для введення шестигранника?
Дан Діну

5
Я думаю, що він хоче створити серійний ключ
Тіаго

Відповіді:


197

Відповідно до MSDN

Створіть 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
Ви завжди повинні говорити, звідки ви берете код, якщо ви кудись копіюєте / вставляєте, інакше це класифікується як плагіат.
DavidG

1
Клас MD5 реалізує IDisposable, не забудьте розпорядитися вашим екземпляром. ;)
Паоло Іомаріні

5
Загалом, ви повинні хеш-кодування тексту без втрат, як UTF8.
Олівер Бок

5
@PrashantPimpale MD5 - алгоритм дайджесту. Подумайте про це як перетворення корови на стейк.
Анант Дабхі

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
Моя відповідь полягала не в тому, щоб позначати кращі практики. Було надано, що ОП поставила його питання. Якби ОП запитала, який найбільш підходящий алгоритм хешування використовувати, відповідь була б іншою (відповідно).
Майкл

8
Я вдячний голосом за те, що за те, що старше двох років, вийшло з контексту. ;)
Михайло

Чому "схожий на формат UNIX"? Що це точно не те саме?
Ігор Гатіс

це дає інший результат від онлайн-шашок md5. чи це просто я ??
bh_earth0

@ Bh_earth0, здається, BitConverterне працює таким же чином , на вікнах і Linux см це питання: stackoverflow.com/questions/11454004 / ...
eddyP23

10

Намагався створити рядкове представлення хешу MD5 за допомогою LINQ, однак жоден з відповідей не був рішеннями LINQ, тому додав це до змішаної межі доступних рішень.

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

return string.Join( "", hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );
Однолінійний

... в такому випадку я пропоную return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );замість цього. Це трохи коротше, можливо, більш чіткий намір і виконує дещо швидше (<10% перф. Збільшення).
Марк.2377,

9

Цілком залежить від того, що ви намагаєтеся досягти. Технічно ви можете просто взяти перші 12 символів з результату хешу MD5, але специфікація MD5 полягає в тому, щоб генерувати 32 символів.

Зменшення розміру хеша знижує безпеку та збільшує ймовірність зіткнень та порушення системи.

Можливо, якщо ви дасте нам більше інформації про те, чого ви намагаєтесь досягти, ми можемо допомогти більше.


+1 Це відповідь, але я теж дуже сумніваюся у безпеці.
лк.

Дякую за вашу відповідь. і шкодую про моє погане пояснення. Я хочу опублікувати додаток для Windows, користувач повинен придбати ліцензію на використання моєї програми, тому мій додаток запитує два поля: USERNAME: ... і KEY: .... Я хочу хеш-код USERNAME і створити KEY , тоді користувач повинен ввести конкретні USERNAME та KEY. моя проблема тут полягає в тому, що KEY має бути 12 символів, (але в хеш-файлі MD5 я отримую 32-знаковий KEY). допоможіть мені, будь ласка, мені це дуже потрібно.
Мухаммад Джафарнеджад

8

Ви можете використовувати Convert.ToBase64Stringдля перетворення 16-байтового виводу MD5 в рядок ~ 24 char. Трохи краще, не знижуючи безпеку. ( j9JIbSY8HuT89/pwdC8jlw==для вашого прикладу)


2
Гарний спосіб вирішення питань, але я сумніваюся, що він захоче мати його з урахуванням регістру та спеціальних характеристик ...
KingCronus

5

Підтримка рядків і потоків файлів.

приклади

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

Я припускаю, що краще використовувати кодування UTF-8 у рядку 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

Хеш MD5 - це 128 біт, тому ви не можете представити його в шістнадцятковій кількості, що містить менше 32 символів ...


Гаразд, я, мабуть, щось тут пропускаю. Як?
лк.

@ lc., вибачте, у моїй відповіді був помилковий помилок, я написав "можна" замість "не можу" ...
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

Більш швидка альтернатива існуючої відповіді для .NET Core 2.1 і вище:

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

Ви можете оптимізувати його ще більше, якщо ви впевнені, що ваші рядки є досить маленькими та замінять кодування.GetBytes небезпечною альтернативою int GetBytes (readOnlySpan chars, Span bytes) альтернативою.


3

Це рішення вимагає c # 8 і користь Span<T>. Зверніть увагу, вам все одно потрібно буде зателефонувати, .Replace("-", string.Empty).ToLowerInvariant()щоб за потреби форматувати результат.

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

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

Я хотів би запропонувати альтернативу, яка, як видається, виконає щонайменше на 10% швидше, ніж відповідь craigdfrench у моїх тестах (.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();
    }
}

Якщо ви хочете мати using System.Runtime.Remoting.Metadata.W3cXsd2001;верхній частині, тіло методу може бути полегшеним для зчитування з одного вкладиша:

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

Досить очевидно, але для повноти в контексті ОП він буде використовуватися як:

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

0

Idk що-небудь про 16 символьних шістнадцяткових рядків ....

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

Але ось моя для створення хеша MD5 в одному рядку.

string hash = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes("THIS STRING TO MD5"))).Replace("-","");
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.