27

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("-", ""); } 
2
  • These days it's better to avoid MD5 as it has known vulnerabilities en.wikipedia.org/wiki/MD5 Commented Jun 30, 2017 at 8:54
  • Good, you helped me! Commented Oct 24 at 8:08

4 Answers 4

16

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(); } 
Sign up to request clarification or add additional context in comments.

3 Comments

That's perfect roufamatic. Does it return a 32 digit hex?
Just tested the function out, and it does exactly what I need - many thanks again.
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.
11

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("-", ""); } 

1 Comment

ToBase64String doesn't return what I want. However, BitConverter.ToString around the byte array does the trick
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())); 

2 Comments

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).
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;.
0

Here is a .NET Standard version that doesn't require reading the entire file into memory:

 private byte[] CalculateMD5OfFile(FileInfo targetFile) { byte[] hashBytes = null; using (var hashcalc = System.Security.Cryptography.MD5.Create()) { using (FileStream inf = targetFile.OpenRead()) hashcalc.ComputeHash(inf); hashBytes = hashcalc.Hash; } return hashBytes; } 

You can convert the byte[] array into a string using the methods shown above. Also: You can change "MD5" in the third line to SHA1, SHA256, etc. to calculate other hashes.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.