文字列から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
なぜヘクスに進入する必要があるのですか?
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 2016

5
一般に、UTF8のようなロスレステキストエンコーディングをハッシュする必要があります。
Oliver Bock 2016

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が使用するのに最も適切なハッシュアルゴリズムを尋ねた場合、その答えは(したがって)異なっていたでしょう。
マイケル

8
2年以上経過したスレッドのコンテキストから外れたものに対する反対票に感謝します。;)
Michael

なぜ「UNIXフォーマットに似ている」のですか?まったく同じではないものは何ですか?
Igor Gatis

これにより、オンラインのmd5チェッカーとは異なる結果が得られます。それとも私だけですか?
bh_earth0

それはそれはそうbh_earth0 @ BitConverterWindowsとLinuxで同じやり方で仕事をしない、この質問を参照してください。stackoverflow.com/questions/11454004/...
eddyP23

10

LINQを使用してMD5ハッシュの文字列表現を作成しようとしていましたが、いずれの回答も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") ) );
Marc.2377

...その場合、return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );代わりに提案します。それは少し短く、おそらくより明確な意図であり、わずかに速く実行されます(10%未満のパフォーマンス向上)。
Marc.2377

9

あなたが達成しようとしていることに完全に依存します。技術的には、MD5ハッシュの結果から最初の12文字だけを取得できますが、MD5の仕様は32文字の文字を生成することです。

ハッシュのサイズを小さくすると、セキュリティが低下し、衝突やシステムが破壊される可能性が高くなります。

おそらく、あなたが達成しようとしていることについて私たちにもっと知らせれば、私たちはより多くのことを支援できるかもしれません。


+1これが答えですが、私も本当にその安全性に疑問を投げかけています。
lc。

ご回答有難うございます。私の悪い説明については申し訳ありません。Windows用のアプリケーションを公開したいのですが、ユーザーはアプリケーションを使用するためのライセンスを購入する必要があるため、アプリケーションはUSERNAME:...とKEY:...の2つのフィールドを要求します。USERNAMEをハッシュしてKEYを作成しますの場合、ユーザーは特定のユーザー名とキーを入力する必要があります。ここでの私の問題は、KEYが12文字である必要があることです(しかし、MD5ハッシュでは、32文字のKEYを取得します)。助けてください、本当に必要です。
Muhamad Jafarnejad

8

を使用Convert.ToBase64Stringして、MD5の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。申し訳ありませんが、私の回答にタイプミスがありました。「できない」ではなく「できる」と書いていました...
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);
    }
}

文字列が十分に小さいことを確認し、encoding.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

私のテストでは、craigdfrenchの答えよりも少なくとも10%高速に動作するように見える代替案を提供したいと思います(.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();
}

自明ですが、完全を期すために、OPのコンテキストでは次のように使用されます。

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

0

16文字の16進文字列については何でも同じです。

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

しかし、これは1行で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.