Calculer un hachage MD5 à partir d'une chaîne


131

J'utilise le code C # suivant pour calculer un hachage MD5 à partir d'une chaîne. Cela fonctionne bien et génère une chaîne hexadécimale de 32 caractères comme celle-ci: 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...

Existe-t-il un moyen d'utiliser un code comme celui-ci pour générer une chaîne hexadécimale de 16 caractères (ou une chaîne de 12 caractères)? Une chaîne hexadécimale de 32 caractères est bonne mais je pense que ce sera ennuyeux pour le client de saisir le code!


7
pourquoi avez-vous besoin que le client entre dans l'hexagone?
Dan Dinu

5
Je pense qu'il veut générer une clé de série
Thiago

Réponses:


197

Selon MSDN

Créer 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
Vous devriez toujours dire d'où vous obtenez le code si vous copiez / collez quelque part, sinon il est classé comme plagiat.
DavidG

1
La classe MD5 implémente IDisposable, pensez à supprimer votre instance. ;)
Paolo Iommarini

5
En général, vous devez hacher un encodage de texte sans perte, comme UTF8.
Oliver Bock

5
@PrashantPimpale MD5 est un algorithme de résumé. Considérez cela comme la conversion d'une vache en 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

13
Ma réponse n'a pas été de mentionner les meilleures pratiques. Il a été fourni dans le contexte que le PO avait formulé sa question. Si l'OP avait demandé quel est l'algorithme de hachage le plus approprié à utiliser, la réponse aurait été différente (en conséquence).
Michael

8
J'apprécie le vote négatif pour quelque chose sorti de son contexte pour un fil de plus de deux ans. ;)
Michael

Pourquoi "similaire au format UNIX"? Qu'est-ce que ce n'est pas exactement la même chose?
Igor Gatis

cela donne un résultat différent des vérificateurs md5 en ligne. ou est-ce juste moi ??
bh_earth0

@ bh_earth0 il semble que BitConvertercela ne fonctionne pas de la même manière sous Windows et Linux, voir cette question: stackoverflow.com/questions/11454004/…
eddyP23

10

J'essayais de créer une représentation sous forme de chaîne de hachage MD5 en utilisant LINQ, cependant, aucune des réponses n'était des solutions LINQ, ajoutant ainsi cela à la panoplie de solutions disponibles.

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

One-liner, dans la syntaxe de la méthode:return string.Join( "", hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );
Marc 2377

... auquel cas, je propose à la return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );place. Son intention est un peu plus courte, peut-être plus claire, et fonctionne légèrement plus rapidement (augmentation des performances <10%).
Marc 2377

9

Cela dépend entièrement de ce que vous essayez d'accomplir. Techniquement, vous pouvez simplement prendre les 12 premiers caractères du résultat du hachage MD5, mais la spécification de MD5 est de générer un 32 caractères.

La réduction de la taille du hachage réduit la sécurité et augmente le risque de collision et de rupture du système.

Peut-être que si vous nous dites plus sur ce que vous essayez d'accomplir, nous pourrons peut-être vous aider davantage.


+1 C'est la réponse, mais moi aussi, je doute vraiment de sa sécurité.
lc.

Merci pour votre réponse. et désolé pour ma mauvaise explication. Je veux publier une application pour Windows, l'utilisateur doit acheter la licence pour utiliser mon application, donc mon application demande deux champs: USERNAME: ... et KEY: .... Je veux hacher le USERNAME et créer la KEY , puis l'utilisateur doit entrer le nom d'utilisateur et la clé spécifiques. mon problème ici est que la clé doit être de 12 caractères, (mais dans le hachage MD5, j'obtiens la clé de 32 caractères). s'il vous plaît aidez-moi, j'en ai vraiment besoin.
Muhamad Jafarnejad

8

Vous pouvez utiliser Convert.ToBase64Stringpour convertir la sortie 16 octets de MD5 en une chaîne de ~ 24 caractères. Un peu mieux sans réduire la sécurité. ( j9JIbSY8HuT89/pwdC8jlw==pour votre exemple)


2
Une belle solution de contournement, mais je doute que l'OP veuille le faire sensible à la casse et avec des caractères spéciaux ...
KingCronus

5

Supporte la chaîne et le flux de fichiers.

exemples

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

Je suppose qu'il est préférable d'utiliser le codage UTF-8 dans la chaîne 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

Un hachage MD5 est de 128 bits, vous ne pouvez donc pas le représenter en hexadécimal avec moins de 32 caractères ...


Ok, je dois manquer quelque chose ici. Comment?
lc.

@lc., désolé, il y avait une faute de frappe dans ma réponse, j'avais écrit "can" au lieu de "can't" ...
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

Une alternative plus rapide à la réponse existante pour .NET Core 2.1 et supérieur:

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

Vous pouvez l'optimiser encore plus si vous êtes sûr que vos chaînes sont suffisamment petites et remplacent encoding.GetBytes by unsafe int GetBytes (ReadOnlySpan chars, Span bytes) alternative.


3

Cette solution nécessite c # 8 et tire parti de Span<T>. Notez que vous devrez toujours appeler .Replace("-", string.Empty).ToLowerInvariant()pour formater le résultat si nécessaire.

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

Je voudrais proposer une alternative qui semble fonctionner au moins 10% plus rapidement que la réponse de craigdfrench dans mes 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();
    }
}

Si vous préférez avoir using System.Runtime.Remoting.Metadata.W3cXsd2001;en haut, le corps de la méthode peut être rendu plus facile à lire en une seule ligne:

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

Assez évident, mais par souci d'exhaustivité, dans le contexte d'OP, il serait utilisé comme:

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

0

Idk quelque chose sur les chaînes hexadécimales de 16 caractères ...

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

Mais voici le mien pour créer un hachage MD5 en une seule ligne.

string hash = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes("THIS STRING TO MD5"))).Replace("-","");
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.