209

I use the following C# code to calculate a MD5 hash from a string. It works well and generates a 32-character hex string like this: 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...

Is there a way to use code like this to generate a 16-character hex string (or 12-character string)? A 32-character hex string is good but I think it'll be boring for the customer to enter the code!

Jonas
  • 4,107
  • 3
  • 21
  • 25
Muhamad Jafarnejad
  • 2,521
  • 4
  • 21
  • 34

21 Answers21

349

As per MSDN

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

        return Convert.ToHexString(hashBytes); // .NET 5 +

        // Convert the byte array to hexadecimal string prior to .NET 5
        // StringBuilder sb = new System.Text.StringBuilder();
        // for (int i = 0; i < hashBytes.Length; i++)
        // {
        //     sb.Append(hashBytes[i].ToString("X2"));
        // }
        // return sb.ToString();
    }
}
Ramon Smits
  • 2,482
  • 1
  • 18
  • 20
Anant Dabhi
  • 10,864
  • 3
  • 31
  • 49
  • 13
    The source: https://msdn.microsoft.com/en-us/library/system.security.cryptography.md5%28v=vs.110%29.aspx – yǝsʞǝla Apr 24 '15 at 06:20
  • 7
    You should always say where you get code from if you copy/paste from somewhere, otherwise it is classed as plagiarism. – DavidG Dec 04 '15 at 11:45
  • 1
    The class MD5 implements IDisposable, remember to dispose your instance. ;) – Paolo Iommarini Feb 28 '16 at 15:43
  • 11
    In general you should hash a lossless text encoding, like UTF8. – Oliver Bock Jul 01 '16 at 01:57
  • 1
    BTW checked with the `BenchmarkDotNet` that the combination of `Cryptography.MD5` and `BitConverter` (see @Michaels's answer) has the best performance. – Monsignor Sep 19 '17 at 07:33
  • if you use UTF8, it puts bytordermark(bom). file_content and string WON'T match. to get rid of bom, i used ``new utf8encoding(false);`` when file.read/write – bh_earth0 Jun 11 '18 at 09:36
  • 1
    Its better to `System.Text.Encoding.Utf8.GetBytes`for people outside of USA. – Richard Schneider Nov 04 '18 at 02:37
  • @Anant How to decrypt the MD5? – Prashant Pimpale Jan 08 '19 at 05:32
  • 14
    @PrashantPimpale MD5 is a digest algorithm. Think of it as converting a cow into a steak. – Anant Dabhi Jan 08 '19 at 06:52
  • Yes tried with `TripleDESCryptoServiceProvider` and done! – Prashant Pimpale Jan 08 '19 at 06:55
  • just wanted to encrypt an Email Id and then decrypt it – Prashant Pimpale Jan 08 '19 at 06:56
  • What does the `"X2"` mean? – Klesun Sep 22 '19 at 14:17
  • 1
    @ArturKlesun , It formats the string as two uppercase hexadecimal characters. – Anant Dabhi Sep 23 '19 at 05:10
  • @PrashantPimpale MD5 is one way - it can create a hash, but information is destroyed and cannot be recovered. It's value comes from hashing two different things then comparing the hashes. Works well for things like passwords, or comparing file contents. If you want to reverse "encryption", the look at things like AES or DES (https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.symmetricalgorithm?view=netcore-3.1). They provide the ability to "encrypt" then "decrypt" – jklemmack Aug 05 '20 at 18:53
  • for those who are trying to calculate for Sip or an equivalent to linux md5sum don't forget to add .ToLower() – Jawad Zeb Feb 19 '21 at 10:47
  • 1
    NOTE: "Due to collision problems with MD5/SHA1, Microsoft recommends SHA256 or SHA512. Consider using the SHA256 class or the SHA512 class instead of the MD5 class. Use MD5 only for compatibility with legacy applications and data." Sources: 1) [MD5 Docs linked by OP](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.md5?redirectedfrom=MSDN&view=net-5.0#remarks), where this notice appears, and 2) [MS Docs on SHA256](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.sha256?view=net-5.0), with a good example – Kurtis Jungersen Sep 14 '21 at 17:03
  • Using BitConverter.ToString() also gives a nice hash-string! – Ivandro Jao Mar 19 '22 at 12:52
  • Microsoft [says](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1850) that "it's more efficient to use the static HashData methods than to create and manage a HashAlgorithm instance to call ComputeHash". Example: `MD5.HashData(bytes)` – mcont Aug 17 '23 at 13:34
107
// 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
Bojidar Stanchev
  • 468
  • 5
  • 20
Michael
  • 3,821
  • 2
  • 19
  • 18
  • Why "similar to UNIX format"? What it is not exactly the same? – Igor Gatis Jun 12 '15 at 12:47
  • this gives different result from online md5 checkers. or is it just me?? – bh_earth0 Jun 11 '18 at 08:40
  • @bh_earth0 it seems that `BitConverter` doesn't work in the same fashion on windows and linux, see this question: https://stackoverflow.com/questions/11454004/calculate-a-md5-hash-from-a-string/24031467#24031467 – eddyP23 Jul 04 '19 at 11:08
23

Was trying to create a string representation of MD5 hash using LINQ, however, none of the answers were LINQ solutions, therefore adding this to the smorgasbord of available solutions.

string result;
using (MD5 hash = MD5.Create())
{
    result = String.Join
    (
        "",
        from ba in hash.ComputeHash
        (
            Encoding.UTF8.GetBytes(observedText)
        ) 
        select ba.ToString("x2")
    );
}
craigdfrench
  • 972
  • 10
  • 20
  • 2
    One-liner, in method syntax: `return string.Join( "", hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );` – Marc.2377 Nov 24 '19 at 20:53
  • 2
    ... in which case, I propose `return string.Concat( hash.ComputeHash( Encoding.UTF8.GetBytes(observedText) ).Select( x => x.ToString("x2") ) );` instead. It's a little bit shorter, possibly clearer intention, and performs marginally faster (<10% perf. increase). – Marc.2377 Nov 27 '19 at 00:17
  • Use `X2` for uppercase hash and `x2` for lowercase hash – Pierre May 04 '23 at 19:47
12

You can use Convert.ToBase64String to convert 16 byte output of MD5 to a ~24 char string. A little bit better without reducing security. (j9JIbSY8HuT89/pwdC8jlw== for your example)

L.B
  • 114,136
  • 19
  • 178
  • 224
  • 2
    A nice workaround, but I doubt he OP will want to have it case-sensitive and with special chars... – KingCronus Jul 12 '12 at 15:14
  • This worked nicely for me when trying to convert an MD5 Hash (from Azure Blob properties) into a string. It produces exactly the same string as the Azure Storage container does. – Detail Nov 25 '20 at 13:19
10

Depends entirely on what you are trying to achieve. Technically, you could just take the first 12 characters from the result of the MD5 hash, but the specification of MD5 is to generate a 32 char one.

Reducing the size of the hash reduces the security, and increases the chance of collisions and the system being broken.

Perhaps if you let us know more about what you are trying to achieve we may be able to assist more.

KingCronus
  • 4,509
  • 1
  • 24
  • 49
  • thanks for your answer. and sorry about my bad explanation. I want to publish an application for windows, the user should buy the license to use my application, so my application request two fields: USERNAME: ... , and KEY: .... I want to hash the USERNAME and create the KEY, then the user should enter the specific USERNAME and KEY. my problem here is that the KEY should be 12-characters, (But in MD5 hash, I get the 32-char KEY). please help me, i really need it. – Muhamad Jafarnejad Jul 12 '12 at 17:21
9

I suppose it is better to use UTF-8 encoding in the string 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();        
}
Tomas Kubes
  • 23,880
  • 18
  • 111
  • 148
8
public static string Md5(string input, bool isLowercase = false)
{
    using (var md5 = MD5.Create())
    {
        var byteHash = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
        var hash = BitConverter.ToString(byteHash).Replace("-", "");
        return (isLowercase) ? hash.ToLower() : hash;
    }
}
Mariusz Jamro
  • 30,615
  • 24
  • 120
  • 162
O Thạnh Ldt
  • 1,103
  • 10
  • 11
7

Support string and file stream.

examples

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);
            }
        }
Think Big
  • 1,021
  • 14
  • 24
6

Idk anything about 16 character hex strings....

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

But here is mine for creating MD5 hash in one line.

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

This solution requires c# 8 and takes advantage of Span<T>. Note, you would still need to call .Replace("-", string.Empty).ToLowerInvariant() to format the result if necessary.

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
  • 7,857
  • 1
  • 23
  • 40
5

Here is my utility function for UTF8, which can be replaced with ASCII if desired:

    public static byte[] MD5Hash(string message)
    {
        return MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(message));
    }
James Hirschorn
  • 7,032
  • 5
  • 45
  • 53
4

A MD5 hash is 128 bits, so you can't represent it in hex with less than 32 characters...

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
4
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
  • 121
  • 9
4

A faster alternative of existing answer for .NET Core 2.1 and higher:

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

You can optimize it even more if you are sure that your strings are small enough and replace encoding.GetBytes by unsafe int GetBytes(ReadOnlySpan chars, Span bytes) alternative.

Tomas Kubes
  • 23,880
  • 18
  • 111
  • 148
4

Extending Anant Dabhi's answer

a helper method:

using System.Text;

namespace XYZ.Helpers
{
    public static class EncryptionHelper
    {
        public static string ToMD5(this 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();
            }
        }
    }
}
Kugan Kumar
  • 423
  • 1
  • 8
  • 14
3

I'd like to offer an alternative that appears to perform at least 10% faster than craigdfrench's answer in my 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();
    }
}

If you prefer to have using System.Runtime.Remoting.Metadata.W3cXsd2001; at the top, the method body can be made an easier to read one-liner:

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

Obvious enough, but for completeness, in OP's context it would be used as:

sSourceData = "MySourceData";
tmpHash = GetMD5Hash(sSourceData);
Marc.2377
  • 7,807
  • 7
  • 51
  • 95
2

https://learn.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);

            }
boubkhaled
  • 379
  • 5
  • 6
2

If you are using a version lower than .NET5 this is a neat way to write it

string.Concat(yourHashBytes.Select(x => x.ToString("X2")))

kemal
  • 21
  • 2
  • 1
    Kindly add more details to your answer, explanations on how your code works and how this address the OP's question would be a great help not just for the asker but also for the future researchers. – Kuro Neko May 20 '22 at 03:38
1
StringBuilder sb= new StringBuilder();
for (int i = 0; i < tmpHash.Length; i++)
{
   sb.Append(tmpHash[i].ToString("x2"));
}
Suhrob Samiev
  • 1,528
  • 1
  • 25
  • 57
1
    public static string GetMD5(string encryptString)
    {
        var passByteCrypt = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(encryptString));

        return ByteArrayToString(passByteCrypt);
    }
    public static string ByteArrayToString(byte[] bytes)
    {
        var output = new StringBuilder(bytes.Length);

        foreach (var t in bytes)
        {
            output.Append(t.ToString("X2"));
        }

        return output.ToString().ToLower();
    }

this is simple md5 ByteCrypt

Smar ts
  • 49
  • 5
0

Here is a condensed version.

private string CreateMD5(string myText)
{
    var hash = System.Security.Cryptography.MD5.Create()
        .ComputeHash(System.Text.Encoding.ASCII.GetBytes(myText ?? ""));
    return string.Join("", Enumerable.Range(0, hash.Length).Select(i => hash[i].ToString("x2")));
}
thalacker
  • 2,389
  • 3
  • 23
  • 44