Md5 Verifier is a tiny simple application that checks the checksum of a file against its expected checksum. A checksum, as you might already know, essentially lets you verify the file you're downloading hasn't been changed or damaged.

Md5Verifier takes an executable and a file containing the md5 checksum, and lets you know if they match.

To interested parties: md5 hashing is built-in for .NET, so implementing a checksum verifier becomes as easy as:

  1. Read the file's data
  2. Compute the file's checksum
  3. Read the (expected) checksum from file
  4. Compare the two values
  5. Display result

Disclaimer: I claim to be no expert in security. If I made any blunders or if there's a better way to do the same, let me know! :)


/// <summary>
/// Reads data from a stream until the end is reached. The 
/// data is returned as a byte array. Throws an IOException 
/// if any of the underlying IO calls fail.
/// </summary>
/// <param name="path">Path to the file to read</param>
/// <returns>The contents of the file</returns>
private byte[] ReadFully(string path)
{
    // Thank you, yoda.arachsys.com

int size = 32768;                       // Size of the buffer: 32K
int read = 0;                           // How many bytes did we read? 
int chunk = 0;                          // Bytes read in the current iteration 

byte[] buffer = new byte[size];         // Holds the contents of the file 

path = Path.GetFullPath(path);          // Is this necessary? 

using (FileStream stream = File.OpenRead(path))
{
    while ((chunk = stream.Read(buffer, read, buffer.Length - read)) &gt; 0)
    {
        read = read + chunk;

        if (read == buffer.Length)
        {
            int nextByte = stream.ReadByte();

            if (nextByte == -1)
            {
                // End of stream, so we're done
                return buffer;
            }

            // Still have more information to read, so let's 
            // resize the buffer. 
            byte[] newBuffer = new byte[buffer.Length * 2];

            Array.Copy(buffer, newBuffer, buffer.Length);

            newBuffer[read] = (byte)nextByte;

            buffer = newBuffer;

            read++;
        }
    }
}

// Get rid of any empty slots (the size of the file 
// doesn't need to be a multiple of 32K). 

byte[] contents = new byte[read];

Array.Copy(buffer, contents, read);

return contents;

}


/// <summary>
/// Returns the MD5 hash of the file
/// </summary>
private string Actual
{
    get
    {
        if (string.IsNullOrEmpty(FileTextBox.Text))
        {
            return string.Empty;
        }

    byte[] actualBytes = ComputeMd5(ReadFully(FileTextBox.Text));

    System.Text.StringBuilder actual = new System.Text.StringBuilder();

    foreach (byte b in actualBytes)
    {
        actual.Append(b.ToString("X2"));
    }

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

}

/// <summary> /// Computes the md5 checksum of the contents. /// </summary> private byte[] ComputeMd5(byte[] contents) { <strong>MD5 md5 = new MD5CryptoServiceProvider();

byte[] hash = md5.ComputeHash(contents);&lt;/strong&gt;

return hash;

}


/// <summary>
/// Reads & returns the expected md5 hash
/// </summary>
private string Expected
{
    get
    {
        if (string.IsNullOrEmpty(Md5TextBox.Text))
        {
            return string.Empty;
        }

    string expected = string.Empty;

    using (StreamReader reader = File.OpenText(Md5TextBox.Text))
    {
        expected = reader.ReadToEnd();
    }

    Match m = Regex.Match(expected, @"^[0-9a-z]+", RegexOptions.Multiline);

    if (m.Success == false)
    {
        throw new ArgumentException("Bad MD5 file.");
    }

    else
    {
        expected = m.Value;
    }

    return expected.ToLower();
}

}


/// <summary>
/// Checks the md5 checksum of the file against its 
/// expected md5 checksum.
/// </summary>
protected void CheckButton_Click(object sender, EventArgs e)
{
    if (string.IsNullOrEmpty(FileTextBox.Text) ||
        string.IsNullOrEmpty(Md5TextBox.Text))
    {
        return;
    }

string actual = Actual;
string expected = Expected;

if (string.IsNullOrEmpty(actual) || string.IsNullOrEmpty(expected))
{
    return;
}

MessageBox.Show("Expected: " + expected);
MessageBox.Show("Actual: " + actual);

if (expected == actual)
{
    MessageBox.Show("Success!");
}

else
{
    MessageBox.Show("Failure!");
}

}

Download the solution file