Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>To avoid pull all the file into memory like Dabblernl's solution you'll want to use a FileStream as is discussed in this SO question <a href="https://stackoverflow.com/questions/805730/computing-md5sum-of-large-files-in-c">Computing MD5SUM of large files in C#</a>, but the MD5CryptoServiceProvider does not allow you to add extra data to the end.</p> <p>Thus you need a merged stream like this:</p> <pre><code>public class MergedStream : Stream, IDisposable { Stream s1; Stream s2; public MergedStream(Stream first, Stream second) { s1 = first; s2 = second; } public override int Read(byte[] buffer, int offset, int count) { int s1count = (int)Math.Min((long)count, s1.Length - s1.Position); int bytesRead = 0; if (s1count &gt; 0) { bytesRead += s1.Read(buffer, offset, s1count); } if (s1count &lt; count) { bytesRead += s2.Read(buffer, offset + s1count, count - s1count); } return bytesRead; } public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); } public override bool CanRead { get { return s1.CanRead &amp;&amp; s2.CanRead; } } public override bool CanSeek { get { return s1.CanSeek &amp;&amp; s2.CanSeek; } } public override bool CanWrite { get { return s1.CanWrite &amp;&amp; s2.CanWrite; } } public override void Flush() { s1.Flush(); s2.Flush(); } public override long Length { get { return s1.Length + s2.Length; } } public override long Position { get { return s1.Position + s2.Position; } set { throw new NotImplementedException(); } } public override long Seek(long offset, SeekOrigin origin) { throw new NotImplementedException(); } public override void SetLength(long value) { throw new NotImplementedException(); } void IDisposable.Dispose() { s1.Dispose(); s2.Dispose(); } } </code></pre> <p>Which you can then use like this to salt you file hash</p> <pre><code> FileStream fs = new FileStream(@"c:\text.txt", FileMode.Open); var m = new MemoryStream(ToAnsiiBytes("SALT"), false); var ms = new MergedStream(fs, m); var C = hasher.ComputeHash(ms); PrintHash(Console.Out, C); </code></pre> <p>with ToAnsiiBytes and PrintHash just being utility functions as such:</p> <pre><code> static void HashAndPrint(TextWriter op, string text) { MD5 md5 = new MD5CryptoServiceProvider(); byte[] bytes = ToAnsiiBytes(text); byte[] hash = md5.ComputeHash(bytes); PrintHash(Console.Out, hash); Console.Out.WriteLine( " = {0}", text); } </code></pre> <p>and </p> <pre><code> public static void PrintHash(TextWriter op, byte[] hash) { foreach (byte b in hash) { op.Write("{0:X2}", b); } } </code></pre> <p>when the file c:\text.txt contains the text <em>toto</em> you can run this code to see that the file + salt equals the same as the text "totoSALT"</p> <pre><code> FileStream fs = new FileStream(@"c:\text.txt", FileMode.Open); var hasher = new MD5CryptoServiceProvider(); var A = hasher.ComputeHash(fs); PrintHash(Console.Out, A); Console.Out.WriteLine(); var salt = new byte[] { 0x53, 0x41, 0x4C, 0x54 }; var B = hasher.ComputeHash(ToAnsiiBytes("SALT")); PrintHash(Console.Out, B); Console.Out.WriteLine(); var m = new MemoryStream(ToAnsiiBytes("SALT"), false); fs.Seek(0, SeekOrigin.Begin); var ms = new MergedStream(fs, m); var C = hasher.ComputeHash(ms); PrintHash(Console.Out, C); Console.Out.WriteLine(); HashAndPrint(Console.Out, "toto"); HashAndPrint(Console.Out, "totoSALT"); HashAndPrint(Console.Out, "SALT"); </code></pre> <p>with this output</p> <pre><code>F71DBE52628A3F83A77AB494817525C6 8C4F4370C53E0C1E1AE9ACD577DDDBED 308DB2451D6580FEEB09FCF2DC1CEE19 F71DBE52628A3F83A77AB494817525C6 = toto 308DB2451D6580FEEB09FCF2DC1CEE19 = totoSALT 8C4F4370C53E0C1E1AE9ACD577DDDBED = SALT </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload