www.geekybob.com

Just a short, simple blog for Bob to share his thoughts.

Simple Utility to Calculate File Hashes

16 May 2014 • by Bob • Scripting, Visual Studio, Scripting, Visual Studio

I have to download various files from time-to-time, and it's nice when websites provide checksum hashes so I can validate that the file I just downloaded matches the version on the server. (ON a related note, I wrote a blog several years ago which showed how to create a provider for the IIS FTP service which automatically creates checksum files when files are uploaded to a server; see my Automatically Creating Checksum Files for FTP Uploads blog post for the details.)

In order to calculate hashes for files that I have downloaded, several years ago I wrote a simple command-line application for Windows which uses several of the built-in algorithms in .NET's System.Security.Cryptography. And while I realize that there are probably other tools that provide this same functionality, I have used this little utility for years, and I've had several people ask me for copies. With that in mind, I thought that it might make a nice blog topic if I shared the code with everyone. (Note: It's a really simple sample; the .NET framework does all the real work for this application.)

Without further fanfare, here's the source code. In order to use this code sample, you need to create a new C# project in Visual Studio and choose the Console Application template. When the new project opens, replace the template's code with the following:

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

class Hash
{
    static void Main(string[] args)
    {
        // Verify the correct number of command-line arguments.
        if (args.Length != 2)
        {
            // Show the help message if an incorrect number of arguments was specified.
            ShowHelp();
            return;
        }
        else
        {
            byte[] hashValue = null;
            // Verify that the specified file exists.
            if (!File.Exists(args[1]))
            {
                // Show the help message if a non-existent filename was specified.
                ShowHelp();
                return;
            }
            else
            {
                try
                {
                    // Create a fileStream for the file.
                    FileStream fileStream = File.OpenRead(args[1]);
                    // Be sure it's positioned to the beginning of the stream.
                    fileStream.Position = 0;
                    // Use the specified hash algorithm.
                    switch (args[0].ToUpper())
                    {
                        case "MD5":
                            // Compute the MD5 hash of the fileStream.
                            hashValue = MD5.Create().ComputeHash(fileStream);
                            break;
                        case "SHA1":
                            // Compute the SHA1 hash of the fileStream.
                            hashValue = SHA1.Create().ComputeHash(fileStream);
                            break;
                        case "SHA256":
                            // Compute the SHA256 hash of the fileStream.
                            hashValue = SHA256.Create().ComputeHash(fileStream);
                            break;
                        case "SHA384":
                            // Compute the SHA384 hash of the fileStream.
                            hashValue = SHA384.Create().ComputeHash(fileStream);
                            break;
                        case "SHA512":
                            // Compute the SHA512 hash of the fileStream.
                            hashValue = SHA512.Create().ComputeHash(fileStream);
                            break;
                        case "BASE64":
                            // Compute the BASE64 hash of the fileStream.
                            byte[] binaryData = new Byte[fileStream.Length];
                            long bytesRead = fileStream.Read(binaryData, 0, (int)fileStream.Length);
                            if (bytesRead != fileStream.Length)
                            {
                                throw new Exception(String.Format("Number of bytes read ({0}) does not match file size ({1}).", bytesRead, fileStream.Length));
                            }
                            string base64String = System.Convert.ToBase64String(binaryData, 0, binaryData.Length);
                            Console.WriteLine("File: {0}\r\nBASE64 Hash: {1}", fileStream.Name, base64String);
                            hashValue = null;
                            break;
                        default:
                            // Display the help message if an unrecognized hash algorithm was specified.
                            ShowHelp();
                            return;
                    }
                    if (hashValue != null)
                    {
                        // Write the hash value to the Console.
                        PrintHashData(args[0].ToUpper(), fileStream.Name, hashValue);
                    }
                    // Close the file.
                    fileStream.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error: {0}", ex.Message);
                }
            }
        }
    }

    // Display the help message.
    private static void ShowHelp()
    {/>        Console.WriteLine("HASH.exe <hash algorithm> <file name>\n\n" +
            "\tWhere <hash algorithm> is one of the following:\n" +
            "\t\tBASE64\n\t\tMD5\n\t\tSHA1\n\t\tSHA256\n\t\tSHA384\n\t\tSHA512\n");
    }

    // Print the hash data in a readable format.
    private static void PrintHashData(string algorithm, string fileName, byte[] array)
    {
        Console.Write("File: {0}\r\n{1} Hash: ", fileName,algorithm);
        for (int i = 0; i < array.Length; i++)
        {
            Console.Write(String.Format("{0:X2}", array[i]));
        }
        Console.WriteLine();
    }/>}

When you compile and run the application, you will see following help message when you specify no command-line parameters:


HASH.exe <hash algorithm> <file name> Where <hash algorithm> is one of the following: BASE64 MD5 SHA1 SHA256 SHA384 SHA512

When you specify one of the supported hashing algorithms and a filename, the application will display something like the following example:


C:\>hash.exe SHA1 foobar.zip File: C:\foobar.zip SHA1 Hash: 57686F6120447564652C20426F6220526F636B73

That's all there is to it. As I mentioned earlier, it's a pretty simple sample. ;-]


Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/


Tags: Visual Studio, Scripting, C#, FTP

Disclaimer

All content within this blog represents my personal views and opinions only. This content is not intended to represent the views, positions, or strategies of my employer or any other organization with which I may be associated. All content and code samples are provided "as is" without warranty of any kind.