How do I create an MD5 hash digest from a text file?

17,854

Solution 1

Here's the routine I'm currently using.

    using System.Security.Cryptography;

    public string HashFile(string filePath)
    {
        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            return HashFile(fs);
        }
    }

    public string HashFile( FileStream stream )
    {
        StringBuilder sb = new StringBuilder();

        if( stream != null )
        {
            stream.Seek( 0, SeekOrigin.Begin );

            MD5 md5 = MD5CryptoServiceProvider.Create();
            byte[] hash = md5.ComputeHash( stream );
            foreach( byte b in hash )
                sb.Append( b.ToString( "x2" ) );

            stream.Seek( 0, SeekOrigin.Begin );
        }

        return sb.ToString();
    }

Solution 2

Short and to the point. filename is your text file's name:

using (var md5 = MD5.Create())
{
    return BitConverter.ToString(md5.ComputeHash(File.ReadAllBytes(filename))).Replace("-", "");
}

Solution 3

This can be achieved by GetHashCode with overloads, allowing to pass either a filePath, a StreamReader or a Stream:

private static string GetHashCode(string filePath, HashAlgorithm cryptoService = null)
    => GetHashCode(fStream: new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), cryptoService);

private static string GetHashCode(StreamReader fileStreamReader, HashAlgorithm cryptoService = null)
    => GetHashCode(fileStreamReader.BaseStream, cryptoService);


/// <summary>
/// Compute hash code for file.
/// </summary>
/// <param name="fStream"></param>
/// <param name="cryptoService">This can be either MD5, SHA1, SHA256, SHA384 or SHA512</param>
/// <returns>Hash string</returns>
private static string GetHashCode(Stream fStream, HashAlgorithm cryptoService = null)
{

    // create or use the instance of the crypto service provider
    // this can be either MD5, SHA1, SHA256, SHA384 or SHA512
    using (cryptoService ??= System.Security.Cryptography.SHA512.Create())
    {
        using var tmpStream = fStream;
        var hash = cryptoService.ComputeHash(tmpStream);
        var hashString = Convert.ToBase64String(hash);
        return hashString.TrimEnd('=');
    }
} // method

Usage:

WriteLine("Default Sha512 Hash Code   : {0}", GetHashCode(FilePath));

Or:

WriteLine("MD5 Hash Code   : {0}", GetHashCode(FilePath, new MD5CryptoServiceProvider()));
WriteLine("SHA1 Hash Code  : {0}", GetHashCode(FilePath, new SHA1CryptoServiceProvider()));
WriteLine("SHA256 Hash Code: {0}", GetHashCode(FilePath, new SHA256CryptoServiceProvider()));
WriteLine("SHA384 Hash Code: {0}", GetHashCode(FilePath, new SHA384CryptoServiceProvider()));
WriteLine("SHA512 Hash Code: {0}", GetHashCode(FilePath, new SHA512CryptoServiceProvider()));
Share:
17,854

Related videos on Youtube

Craig Schwarze
Author by

Craig Schwarze

A software development manager and architect, with extensive experience in enterprise application development using a range of technologies, mostly in the Microsoft technical space. Find me on LinkedIn!

Updated on April 15, 2022

Comments

  • Craig Schwarze
    Craig Schwarze about 2 years

    Using C#, I want to create an MD5 hash of a text file. How can I accomplish this?

    Update: Thanks to everyone for their help. I've finally settled upon the following code -

    // Create an MD5 hash digest of a file
    public string MD5HashFile(string fn)
    {            
        byte[] hash = MD5.Create().ComputeHash(File.ReadAllBytes(fn));
        return BitConverter.ToString(hash).Replace("-", "");            
    }
    
  • Craig Schwarze
    Craig Schwarze over 14 years
    That's perfect roufamatic. Does it return a 32 digit hex?
  • Craig Schwarze
    Craig Schwarze over 14 years
    Just tested the function out, and it does exactly what I need - many thanks again.
  • roufamatic
    roufamatic over 14 years
    If you don't need to reuse the stream you can of course remove all that code. This used to be in a pipeline of sorts so that the stream could be hashed first, then gzipped. Now I mostly just care about the hash, hence the shortcut.
  • Craig Schwarze
    Craig Schwarze over 14 years
    ToBase64String doesn't return what I want. However, BitConverter.ToString around the byte array does the trick
  • Matt
    Matt over 2 years
    Good solution! I suggest a little improvement: Make the 2nd parameter nullable i.e. HashAlgorithm cryptoService = null and then add a default provider like so: using (cryptoService ??= System.Security.Cryptography.SHA512.Create()) - or if you prefer, you can use MD5 too (but I would not recommend it). This will simplify usage while keeping maximum flexibility (you are still able to add the provider of your choice).
  • Matt
    Matt over 2 years
    Hint (for those who need it): In case you need a StreamReader (fileStreamReader) instead of a filepath as a parameter, you can create an overload of this function where you do like using var fileStream = fileStreamReader.BaseStream;.