Berechnen Sie einen MD5-Hash aus einer Zeichenfolge

131

Ich verwende den folgenden C # -Code, um einen MD5-Hash aus einer Zeichenfolge zu berechnen. Es funktioniert gut und generiert eine 32-stellige Hex-Zeichenfolge wie folgt: 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...

Gibt es eine Möglichkeit, Code wie diesen zu verwenden, um eine 16-stellige Hex-Zeichenfolge (oder eine 12-stellige Zeichenfolge) zu generieren? Eine 32-stellige Hex-Zeichenfolge ist gut, aber ich denke, es wird für den Kunden langweilig sein, den Code einzugeben!

Muhamad Jafarnejad
quelle
7
Warum muss der Kunde das Hex eingeben?
Dan Dinu
5
Ich denke, dass er einen Serienschlüssel generieren möchte
Thiago

Antworten:

197

Wie pro MSDN

MD5 erstellen:

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
quelle
9
Die Quelle: msdn.microsoft.com/en-us/library/…
yǝsʞǝla
5
Sie sollten immer angeben, woher Sie Code beziehen, wenn Sie von irgendwoher kopieren / einfügen, andernfalls wird er als Plagiat eingestuft.
DavidG
1
Die Klasse MD5 implementiert IDisposable. Denken Sie daran, Ihre Instanz zu entsorgen. ;)
Paolo Iommarini
5
Im Allgemeinen sollten Sie eine verlustfreie Textcodierung wie UTF8 hashen.
Oliver Bock
5
@PrashantPimpale MD5 ist ein Digest-Algorithmus. Stellen Sie sich vor, Sie verwandeln eine Kuh in ein 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
quelle
13
Meine Antwort war nicht, Best Practices zu bezeichnen. Es wurde im Zusammenhang vorgesehen, dass das OP seine Frage formuliert hatte. Hätte das OP gefragt, welcher Hashing-Algorithmus am besten geeignet ist, wäre die Antwort (entsprechend) anders ausgefallen.
Michael
8
Ich schätze die Abwertung für etwas, das für einen über zwei Jahre alten Thread aus dem Zusammenhang gerissen wurde. ;)
Michael
Warum "ähnlich dem UNIX-Format"? Was ist es nicht genau das gleiche?
Igor Gatis
Dies ergibt ein anderes Ergebnis als bei Online-MD5-Prüfern. oder bin es nur ich?
bh_earth0
@ bh_earth0 es scheint, dass unter BitConverterWindows und Linux nicht auf die gleiche Weise funktioniert, siehe diese Frage: stackoverflow.com/questions/11454004/…
eddyP23
10

Beim Versuch, eine Zeichenfolgendarstellung von MD5-Hash mit LINQ zu erstellen, handelte es sich bei keiner der Antworten um LINQ-Lösungen, weshalb dies dem Smorgasbord der verfügbaren Lösungen hinzugefügt wurde.

string result;
using (MD5 hash = MD5.Create())
{
    result = String.Join
    (
        "",
        from ba in hash.ComputeHash
        (
            Encoding.UTF8.GetBytes(observedText)
        ) 
        select ba.ToString("x2")
    );
}
craigdfrench
quelle
return string.Join( "", hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );
Einzeiler
... in diesem Fall schlage ich return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );stattdessen vor. Es ist etwas kürzer, möglicherweise klarer und arbeitet geringfügig schneller (<10% Leistungssteigerung).
März 2377
9

Kommt ganz darauf an, was Sie erreichen wollen. Technisch gesehen könnten Sie nur die ersten 12 Zeichen aus dem Ergebnis des MD5-Hashs entnehmen, aber die Spezifikation von MD5 besteht darin, ein 32-Zeichen-Zeichen zu generieren.

Das Reduzieren der Größe des Hash verringert die Sicherheit und erhöht die Wahrscheinlichkeit von Kollisionen und Systemausfällen.

Wenn Sie uns mehr darüber mitteilen, was Sie erreichen möchten, können wir Ihnen möglicherweise weiterhelfen.

KingCronus
quelle
+1 Dies ist die Antwort, aber auch ich stelle die Sicherheit wirklich in Frage.
lc.
Danke für deine Antwort. und Entschuldigung für meine schlechte Erklärung. Wenn ich eine Anwendung für Windows veröffentlichen möchte, sollte der Benutzer die Lizenz zur Verwendung meiner Anwendung kaufen, daher fordert meine Anwendung zwei Felder an: USERNAME: ... und KEY: .... Ich möchte den USERNAME hashen und den KEY erstellen Dann sollte der Benutzer den spezifischen USERNAME und den KEY eingeben. Mein Problem hier ist, dass der SCHLÜSSEL 12 Zeichen lang sein sollte (aber in MD5-Hash bekomme ich den 32-stelligen SCHLÜSSEL). Bitte hilf mir, ich brauche es wirklich.
Muhamad Jafarnejad
8

Sie können Convert.ToBase64Stringdie 16-Byte-Ausgabe von MD5 in eine Zeichenfolge mit ~ 24 Zeichen konvertieren. Ein bisschen besser, ohne die Sicherheit zu beeinträchtigen. ( j9JIbSY8HuT89/pwdC8jlw==für dein Beispiel)

PFUND
quelle
2
Eine nette Problemumgehung, aber ich bezweifle, dass der OP zwischen Groß- und Kleinschreibung und speziellen Zeichen unterscheiden
möchte
5

Unterstützt String und Dateistream.

Beispiele

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);
            }
        }
Groß denken
quelle
4

Ich nehme an, es ist besser, die UTF-8-Codierung in der Zeichenfolge MD5 zu verwenden.

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
quelle
3

Ein MD5-Hash ist 128 Bit, Sie können ihn also nicht mit weniger als 32 Zeichen hexadezimal darstellen ...

Thomas Levesque
quelle
Ok, mir muss hier etwas fehlen. Wie?
lc.
@lc., sorry, es gab einen Tippfehler in meiner Antwort, ich hatte "kann" statt "kann nicht" geschrieben ...
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
quelle
3

Diese Lösung erfordert c # 8 und nutzt Span<T>. Beachten Sie, dass Sie bei Bedarf immer noch aufrufen müssen, um .Replace("-", string.Empty).ToLowerInvariant()das Ergebnis zu formatieren.

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.
quelle
2

Eine schnellere Alternative zur vorhandenen Antwort für .NET Core 2.1 und höher:

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

Sie können es noch weiter optimieren, wenn Sie sicher sind, dass Ihre Zeichenfolgen klein genug sind und die Codierung ersetzen. GetBytes durch unsichere int GetBytes-Alternative (ReadOnlySpan-Zeichen, Span-Bytes).

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

Ich möchte eine Alternative anbieten, die mindestens 10% schneller zu sein scheint als die Antwort von craigdfrench in meinen Tests (.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();
    }
}

Wenn Sie es vorziehen, oben zu haben using System.Runtime.Remoting.Metadata.W3cXsd2001;, kann der Methodenkörper zu einem leichter lesbaren Einzeiler gemacht werden:

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

Offensichtlich, aber der Vollständigkeit halber würde es im Kontext von OP verwendet als:

sSourceData = "MySourceData";
tmpHash = GetMD5Hash(sSourceData);
März 2377
quelle
0

Idk alles über 16 Zeichen Hex-Strings ....

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

Aber hier ist meine zum Erstellen von MD5-Hash in einer Zeile.

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