Commentary
Hash Totals

by John Lansdale

A hash algorithm (one doesn’t call something like this a mere program) will read a file or a long string of characters and turn it into a single 32-character string so unique that, with the MD5 algorithm I’m talking about here, there’s only a 1 in a giant number (~3.4 x 1038) chance of two strings coming up with the same hash. Hashes have several practical uses.

Cryptography is one. Instead of storing passwords directly in a database, where anyone can read them, they can be hashed first. The result is unreadable gibberish, but they can still be used for verification. All the verifying program has to do is recalculate the hash for a challenging password and compare to the stored hash value. The hash algorithm calculates the same hash for the same input string every time.

I came across another use of hashes today while preparing for this month’s Server SIG (Jim’s out, I’m substituting). Rob and I are going to try to install the very newest Ubuntu 7.04 server edition. I downloaded the .iso file from http://mirror.cc.columbia.edu/pub/linux/ubuntu/releases/7.04/ which I found on the Ubuntu site http://www.ubuntu.com/getubuntu/download. Last time I downloaded an Ubuntu file it didn’t work correctly so this time I read their advice about checking the MD5 hash total.

Someone at the mirror (download) site calculates a hash for the whole file and stores it as a string in a public directory. Anyone can check that their download worked by recalculating a hash on the same file.

In the mirror directory I used, there’s a text file named MD5SUM. It contains a list of hashes for the files in that directory. For the file I wanted to check it listed:

cf462501e2dc1b82b96dfc497a0404a2 *Ubuntu-7.04-server-i386.iso

I’m doing this in Windows XP. To re-compute I downloaded and used an open source program Ubuntu recommended for calculating the MD5 hash in Windows MD5. Its name is winMd5Sum, you can get it at http://infrarecorder.sourceforge.net/. When it installs, it creates a link in your “Send To” folder. I right-clicked on the downloaded file, took “Send To” and winMd5Sum. After a couple of minutes (it had to read the whole 500 meg file) a box popped up with the computed Md5 sum. I just copied and pasted the number I got from the MD5SUM file and clicked “compare”, the numbers were the same so I’m sure I got the correct file.

But, this piqued my curiosity. I wondered if MD5 really is the same MD5 no matter in which platform it’s calculated. I had just been reading about cryptography in my C# Microsoft certification test book so I figured it would be good practice and not too hard to write a similar program on my own. I also know PHP5 and figured it should work there too. So, I tried that too. Both worked.

I didn’t write the MD5 algorithm itself, I just used the proper system classes and functions. Its not just because of the difficulty. Since it’s a kind of standard it’s really better to have it written at a higher level.

Here’s the C# program. It’s a not a very object oriented console program that calculates the MD5 hash for a given file name. Note you need the name spaces for Cryptography and IO.

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace MyMD5
{
    class Program
    {
        //
        // Command line program to calculate MD5 hash.
        // 
        static void Main(string[] args)
        {
            Console.WriteLine("MD5 Hash Generator");
            // Get a valid file name and turn it into a Stream
            string fName ="";
            bool validatedFile = false;
            if (args.Length == 1) fName = args[0] ;
            try
            {
                while (validatedFile == false)
                {
                    if (fName == "")
                    {
                        Console.WriteLine("Enter valid file name. Or just press enter to end.");
                        fName = Console.ReadLine();
                        if (fName == "") Environment.Exit(1);
                    }
                    FileInfo fi = new FileInfo(fName);
                    if (fi.Exists) validatedFile = true;
                }
                FileStream sr = new FileStream(fName, FileMode.Open);
                // Do the cryptography, get byte array hash
                MD5CryptoServiceProvider md5 =
                  new MD5CryptoServiceProvider();
                byte[] data = md5.ComputeHash(  sr );
                sr.Close(); // through with it now
                // Format the byte array for reading
                StringBuilder hashString = new StringBuilder();
                for (int i = 0; i < data.Length; i++)
                {
                    hashString.Append(data[i].ToString("x2"));
                }
		
                // Show it
                Console.WriteLine("\nMD5 hash is: {0}", hashString);
                Console.ReadLine();
            }
            catch (Exception e)
            {
                // Any trouble goes here
                Console.WriteLine(e.Message);
            }
        }
    }
}
	

OUTPUT:

MD5 Hash Generator
Enter valid file name you want MD5 sum for. Or just press enter to end.
C:\Data\Downloads\Ubuntu704\Ubuntu-7.04-server-i386.iso
MD5 hash is: cf462501e2dc1b82b96dfc497a0404a2

Of course, a finished version would have a nice Windows file chooser dialog or maybe, instead of prompting, an output with a result that could be used in scripting. But for this, I just used an old trick (you may have a better one – someone please tell me if this works in Windows Vista) to avoid typing long file names.

And, here’s the PHP:

<?php
     $fName = "";
     $md5Hash = "";
     if ($_GET['fName'] != "")
     {
         $fName = $_GET['fName'] ;
         if (file_exists($fName) )
  	     $md5Hash = hash_file('md5', "$fName"); 
     }
?>
<html>
<body>
<h2>MD5 Hash Generator</h2>
<form name="form1" action="test5.php" method="get">
File name: 
   <input type="text" size="70" name="fName" value="<?= $fName?>">
<br><br>
<input type="submit" value="Calculate MD5">
</form>
<?     if ($md5Hash !="") print( "<b>Hash</b>: $md5Hash") ;
   elseif ($fName != "")  print("<b><i>Enter valid file name including drive letter.</i></b>"); 
?>
</body>
</html>

OUTPUT:

PHP MD5 Output

You will note, the hash number is the same! Columbia university, Microsoft and Zend (the PHP language creator) all agree.

 

 


DacsGear!
Mugs and more, visit CafePress to order
 
 
© Danbury Area Computer Society, Inc. All Rights Reserved.
Web Site Terms & Conditions of Use