Bir dizeden bir MD5 hash hesaplayın


131

Bir dizeden bir MD5 karmasını hesaplamak için aşağıdaki C # kodunu kullanıyorum. İyi çalışır ve aşağıdaki gibi 32 karakterlik bir onaltılık dize oluşturur: 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...

16 karakterlik bir onaltılık dize (veya 12 karakterlik bir dize) oluşturmak için böyle bir kod kullanmanın bir yolu var mı? 32 karakterlik onaltılık bir dize iyidir, ancak müşterinin kodu girmesinin sıkıcı olacağını düşünüyorum!


7
müşterinin onaltılık alana girmesine neden ihtiyacınız var?
Dan Dinu

5
Sanırım bir seri anahtar üretmek istiyor
Thiago 18'13

Yanıtlar:


197

Gereğince MSDN

MD5 oluştur:

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
Bir yerden kopyalayıp yapıştırırsanız her zaman kodu nereden aldığınızı söylemelisiniz, aksi takdirde intihal olarak sınıflandırılır.
DavidG

1
MD5 sınıfı, IDisposable uygular, örneğinizi elden çıkarmayı unutmayın. ;)
Paolo Iommarini

6
Genel olarak, UTF8 gibi kayıpsız bir metin kodlamasına hash uygulamanız gerekir.
Oliver Bock

5
@PrashantPimpale MD5 bir özet algoritmadır. Bir ineği bifteğe dönüştürmek olarak düşünün.
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
Cevabım en iyi uygulamaları belirtmek değildi. OP'nin sorusunu çerçevelendirdiği bağlamda sağlandı. OP, kullanılacak en uygun hash algoritmasının ne olduğunu sormuş olsaydı, cevap farklı olurdu (buna göre).
Michael

8
İki yıldan daha eski bir konu için bağlamın dışına çıkarılan bir şey için olumsuz oyu takdir ediyorum. ;)
Michael

Neden "UNIX biçimine benzer"? Tam olarak aynı değil ne?
Igor Gatis

bu, çevrimiçi md5 dama oyunlarından farklı sonuçlar verir. yoksa sadece ben miyim?
bh_earth0

@ bh_earth0 BitConverterWindows ve linux üzerinde aynı şekilde çalışmıyor gibi görünüyor, şu soruya bakın: stackoverflow.com/questions/11454004/…
eddyP23

10

LINQ kullanarak bir MD5 hash dizgisi oluşturmaya çalışıyordu, ancak yanıtların hiçbiri LINQ çözümleri değildi, bu nedenle bunu mevcut çözümlerin smorgasbord'una eklediler.

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

Tek return string.Join( "", hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );
satırlık

... bu durumda, return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );onun yerine teklif ediyorum . Biraz daha kısadır, muhtemelen daha net niyet ve marjinal olarak daha hızlı performans gösterir (<% 10 perf. Artış).
Marc. 2377

9

Tamamen ne başarmaya çalıştığınıza bağlıdır. Teknik olarak, MD5 hash'inin sonucundan sadece ilk 12 karakteri alabilirsiniz, ancak MD5'in özelliği 32 karakterlik bir tane üretmektir.

Hash boyutunun küçültülmesi güvenliği azaltır ve çarpışma ve sistemin kırılma olasılığını artırır.

Belki de neyi başarmaya çalıştığınız hakkında bize daha fazla bilgi verirseniz, daha fazla yardımcı olabiliriz.


+1 Cevap bu, ama ben de gerçekten güvenliğini sorguluyorum.
lc.

Cevabınız için teşekkürler. ve kötü açıklamam için özür dilerim. Windows için bir uygulama yayınlamak istiyorum, kullanıcı uygulamamı kullanmak için lisans satın almalı, bu nedenle uygulamam iki alan istiyor: KULLANICIADI: ... ve KEY: .... KULLANICI ADI'na hashing uygulamak ve KEY'i oluşturmak istiyorum , ardından kullanıcı belirli KULLANICI ADI ve ANAHTAR girmelidir. Buradaki sorunum, ANAHTAR'ın 12 karakter olması gerektiğidir (Ancak MD5 karmasında 32 karakterli ANAHTARI alıyorum). lütfen bana yardım et, gerçekten ihtiyacım var.
Muhamad Jafarnejad

8

Convert.ToBase64StringMD5'in 16 bayt çıktısını ~ 24 karakterlik bir dizeye dönüştürmek için kullanabilirsiniz . Güvenliği düşürmeden biraz daha iyi. ( j9JIbSY8HuT89/pwdC8jlw==örneğiniz için)


2
Güzel bir çözüm, ancak OP'nin büyük / küçük harfe duyarlı olmasını ve özel karakterlerle
olmasını isteyeceğinden şüpheliyim

5

Destek dizisi ve dosya akışı.

örnekler

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

Sanırım MD5 dizesinde UTF-8 kodlamasını kullanmak daha iyidir.

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

Bir MD5 hash'i 128 bittir, bu nedenle onu 32'den az karakterle onaltılık olarak gösteremezsiniz ...


Tamam, burada bir şey eksik olmalı. Nasıl?
lc.

@lc., üzgünüm, cevabımda bir yazım hatası vardı, "yapamam" yerine "can" yazmıştım ...
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 ve üstü için mevcut yanıtın daha hızlı bir alternatifi:

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

Dizelerinizin yeterince küçük olduğundan ve encoding.GetBytes yerine güvenli olmayan int GetBytes (ReadOnlySpan chars, Span bayt) alternatifi ile değiştirdiğinizden eminseniz bunu daha da optimize edebilirsiniz.


3

Bu çözüm c # 8 gerektirir ve Span<T>. .Replace("-", string.Empty).ToLowerInvariant()Gerekirse sonucu biçimlendirmek için yine de aramanız gerekeceğini unutmayın .

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

Testlerimde craigdfrench'in yanıtından en az% 10 daha hızlı performans gösteren bir alternatif sunmak istiyorum (.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;En üstte olmasını tercih ederseniz , yöntem gövdesi tek satırlık okumayı kolaylaştırabilir:

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

Yeterince açık, ancak tamlık için OP bağlamında şu şekilde kullanılacaktır:

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

0

16 karakterlik onaltılık dizelerle ilgili herhangi bir şeyi idk ...

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

Ama işte tek satırda MD5 hash oluşturmak için benimki.

string hash = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes("THIS STRING TO MD5"))).Replace("-","");
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.