문자열에서 MD5 해시 계산


131

다음 C # 코드를 사용하여 문자열에서 MD5 해시를 계산합니다. 그것은 잘 작동하고 다음과 같이 32 문자 16 진수 문자열을 생성합니다 : 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 자 16 진 문자열 (또는 12 자 문자열)을 생성하는 방법이 있습니까? 32 자 16 진 문자열은 좋지만 고객이 코드를 입력하는 것은 지루할 것입니다!


7
고객이 16 진수를 입력해야하는 이유는 무엇입니까?
Dan Dinu

5
나는 그가 시리얼 키를 생성하고 싶다고 생각합니다
Thiago

답변:


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을 구현합니다. 인스턴스를 폐기해야합니다. ;)
Paolo Iommarini

5
일반적으로 UTF8과 같은 무손실 텍스트 인코딩을 해시해야합니다.
Oliver Bock

5
@PrashantPimpale MD5는 다이제스트 알고리즘입니다. 소를 스테이크로 바꾸는 것으로 생각하십시오.
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
내 대답은 모범 사례를 나타내지 않았습니다. OP가 그의 질문을 구성한 맥락에서 제공되었다. OP가 사용하기에 가장 적합한 해싱 알고리즘이 무엇인지 물었다면 그에 대한 대답은 달라졌을 것입니다.
Michael

8
2 살이 넘은 쓰레드에 대해 맥락에서 벗어난 것에 대한 다운 투표에 감사드립니다. ;)
Michael

왜 "UNIX 형식과 비슷합니까?" 정확히 동일하지 않은 것은 무엇입니까?
Igor Gatis 2016 년

이것은 온라인 md5 검사기와는 다른 결과를 제공합니다. 아니면 그냥 나입니까?
bh_earth0

@ bh_earth0 BitConverterWindows와 Linux에서 동일한 방식으로 작동하지 않는 것 같습니다 . stackoverflow.com/questions/11454004/…
eddyP23

10

LINQ를 사용하여 MD5 해시의 문자열 표현을 만들려고 시도했지만 LINQ 솔루션에 대한 답변은 없었으므로 사용 가능한 솔루션의 smorgasbord에 추가했습니다.

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") ) );
Marc.2377

...이 경우 return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );대신 제안 합니다. 조금 더 짧고, 의도가 더 명확하고, 약간 더 빠릅니다 (<10 % perf. 증가)
Marc.2377

9

달성하려는 것에 전적으로 달려 있습니다. 기술적으로 MD5 해시의 결과에서 처음 12자를 사용할 수 있지만 MD5의 사양은 32자를 생성하는 것입니다.

해시 크기를 줄이면 보안이 떨어지고 충돌 및 시스템이 손상 될 가능성이 높아집니다.

어쩌면 당신이 달성하려는 것에 대해 더 많이 알려 주면 더 많은 도움을 줄 수있을 것입니다.


+1 이것이 답이지만, 나도 그것의 보안에 의문을 제기합니다.
lc.

답변 주셔서 감사합니다. 내 나쁜 설명에 대해 죄송합니다. Windows 용 응용 프로그램을 게시하고 싶습니다. 사용자가 내 응용 프로그램을 사용하려면 라이센스를 구입해야하므로 내 응용 프로그램은 USERNAME : ... 및 KEY : ...의 두 필드를 요청합니다. USERNAME을 해시하고 KEY를 만들고 싶습니다. 사용자는 특정 USERNAME 및 KEY를 입력해야합니다. 내 문제는 KEY가 12 자 여야한다는 것입니다 (그러나 MD5 해시에서는 32 문자 KEY를 얻습니다). 도와주세요. 정말로 필요합니다.
Muhamad Jafarnejad

8

Convert.ToBase64StringMD5의 16 바이트 출력을 ~ 24 자 문자열로 변환 하는 데 사용할 수 있습니다 . 보안을 줄이지 않고 조금 나아졌습니다. ( j9JIbSY8HuT89/pwdC8jlw==예를 들어)


2
좋은 해결 방법이지만 OP가 대소 문자를 구분하고 특수 문자를 사용하고 싶을 것입니다.
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

문자열 MD5에서 UTF-8 인코딩을 사용하는 것이 더 좋다고 생각합니다.

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 자 미만으로 16 진수로 표현할 수 없습니다 ...


좋아, 여기에 뭔가가 빠져 있어야합니다. 어떻게?
lc.

@lc., 죄송합니다. 제 답변에 오타가 있습니다. "ca n't"대신 "can"을 작성했습니다 ...
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);
    }
}

안전하지 않은 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
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

내 테스트 (.NET 4.7.2)에서 craigdfrench의 답변 보다 적어도 10 % 더 빠른 것으로 보이는 대안을 제공하고 싶습니다 .

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

분명하지만 OP의 맥락에서 완전성을 위해 다음과 같이 사용됩니다.

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

0

16 문자 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("-","");
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.