Microsoft KB Archive/307020

= How to compute and compare hash values by using Visual C# =

Article ID: 307020

Article Last Modified on 1/12/2007

-

APPLIES TO


 * Microsoft Visual C# .NET 2002 Standard Edition
 * Microsoft Visual C# 2005

-



This article was previously published under Q307020



For a Microsoft Visual Basic .NET version of this article, see 301053.

This article refers to the following Microsoft .NET Framework Class Library namespaces:
 * System.Security.Cryptography
 * System.Text

IN THIS TASK
SUMMARY
 * Requirements
 * Compute a Hash Value
 * Compare Two Hash Values
 * Complete Code Listing

REFERENCES



SUMMARY
This step-by-step article shows you how to obtain a hash value and how to compare two hash values to check whether they are identical.

The System.Security.Cryptography classes in the Microsoft .NET Framework make it easy to compute a hash value for your source data.

back to the top

Requirements
The following list outlines the recommended hardware, software, network infrastructure, and service packs that you will need:
 * Microsoft Windows 2000 Professional, Windows 2000 Server, Windows 2000 Advanced Server, or Windows NT 4.0 Server
 * Microsoft Visual C# .NET or Microsoft Visual C# 2005

back to the top

Compute a Hash Value
It is easy to generate and compare hash values using the cryptographic resources contained in the System.Security.Cryptography namespace. Because all hash functions take input of type Byte[], it might be necessary to convert the source into a byte array before it is hashed. To create a hash for a string value, follow these steps:  Open Visual Studio .NET or Microsoft Visual Studio 2005. Create a new Console Application in Visual C# .NET or in Visual C# 2005 creates a public class for you along with an empty Main method.

Note In Microsoft Visual C#. NET, Class1.cs is created by default. In Microsoft Visual C# 2005, Program.cs is created by default.  Use the using directive on the System, System.Security.Cryptography and System.Text namespaces so that you are not required to qualify declarations from these namespaces later in your code. These statements must be used prior to any other declarations. using System; using System.Security.Cryptography; using System.Text;   Declare a string variable to hold your source data, and two byte arrays (of undefined size) to hold the source bytes and the resulting hash value. string sSourceData; byte[] tmpSource; byte[] tmpHash;   Use the GetBytes method, which is a member of the System.Text.ASCIIEncoding class, to convert your source string into an array of bytes (required as input to the hashing function). sSourceData = &quot;MySourceData&quot;; //Create a byte array from source data. tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);   Compute the MD5 hash for your source data by calling ComputeHash on an instance of the MD5CryptoServiceProvider class. Note that to compute another hash value, you will need to create another instance of the class. //Compute hash based on source data. tmpHash = new MD5CryptoServiceProvider.ComputeHash(tmpSource);   The tmpHash byte array now holds the computed hash value (128-bit value=16 bytes) for your source data. It is often useful to display or store a value like this as a hexadecimal string, which the following code accomplishes: Console.WriteLine(ByteArrayToString(tmpHash)); static string ByteArrayToString(byte[] arrInput) {   int i;    StringBuilder sOutput = new StringBuilder(arrInput.Length); for (i=0;i < arrInput.Length; i++) {       sOutput.Append(arrInput[i].ToString(&quot;X2&quot;)); }   return sOutput.ToString; }                   </li> Save and then run your code to see the resulting hexadecimal string for the source value.</li></ol>

back to the top

Compare Two Hash Values
One of the purposes of creating a hash from source data is to provide a way to see if data has changed over time, or to compare two values without ever working with the actual values. In either case, you need to compare two computed hashes, which is easy if they are both stored as hexadecimal strings (as in the last step of the above section). However, it is quite possible that they will both be in the form of byte arrays. The following code, which continues from the code created in the previous section, shows how to compare two byte arrays. <ol>  Just below the creation of a hexadecimal string, create a new hash value based on new source data. sSourceData = &quot;NotMySourceData&quot;; tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);

byte[] tmpNewHash; tmpNewHash = new MD5CryptoServiceProvider.ComputeHash(tmpSource); </li>  The most straightforward way to compare two byte arrays is to loop through the arrays, comparing each individual element to its counterpart from the second value. If any elements are different, or if the two arrays are not the same size, the two values are not equal. bool bEqual = false; if (tmpNewHash.Length == tmpHash.Length) {   int i=0; while ((i < tmpNewHash.Length) && (tmpNewHash[i] == tmpHash[i])) {       i += 1; }   if (i == tmpNewHash.Length) {       bEqual = true; } }

if (bEqual) Console.WriteLine(&quot;The two hash values are the same&quot;); else Console.WriteLine(&quot;The two hash values are not the same&quot;); Console.ReadLine; </li> Save and then run your project to view the hexadecimal string created from the first hash value, and to find out if the new hash is equal to the original.</li></ol>

back to the top

Complete Code Listing
using System; using System.Security.Cryptography; using System.Text;

namespace ComputeAHash_csharp {   ///     /// Summary description for Class1. ///    class Class1 {       static void Main(string[] args) {           string sSourceData; byte[] tmpSource; byte[] tmpHash; sSourceData = &quot;MySourceData&quot;; //Create a byte array from source data tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData); //Compute hash based on source data tmpHash = new MD5CryptoServiceProvider.ComputeHash(tmpSource); Console.WriteLine(ByteArrayToString(tmpHash));

sSourceData = &quot;NotMySourceData&quot;; tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);

byte[] tmpNewHash; tmpNewHash = new MD5CryptoServiceProvider.ComputeHash(tmpSource);

bool bEqual = false; if (tmpNewHash.Length == tmpHash.Length) {               int i=0; while ((i < tmpNewHash.Length) && (tmpNewHash[i] == tmpHash[i])) {                   i += 1; }               if (i == tmpNewHash.Length) {                   bEqual = true; }           }

if (bEqual) Console.WriteLine(&quot;The two hash values are the same&quot;); else Console.WriteLine(&quot;The two hash values are not the same&quot;); Console.ReadLine; }

static string ByteArrayToString(byte[] arrInput) {           int i;            StringBuilder sOutput = new StringBuilder(arrInput.Length); for (i=0;i < arrInput.Length -1; i++) {               sOutput.Append(arrInput[i].ToString(&quot;X2&quot;)); }           return sOutput.ToString; }   } } back to the top

<div class="references_section">