Computing a Hash


The ManagedCryptoAPI class includes a method called ManagedComputeHash , which computes a hash for an array of bytes. To use ManagedComputeHash , follow these steps:

  1. Acquire an instance of the ManagedCryptoAPI class.

  2. Use the ManagedCryptoAPI instance to acquire a handle to a key container within a CSP.

  3. Pass the context handle, the array of bytes for which to compute a hash, and a reference to an Int32 to the ManagedComputeHash method.

  4. ManagedComputeHash returns an array of bytes holding the hash bytes and sets the reference to the Int32 to the number of bytes in the returned array that hold valid hash data.

Listing 14.3, taken from the sample application ComputeHash, demonstrates computing a hash with ManagedCryptoAPI . The code first acquires the hash bytes and then paints them into a textbox.

Listing 14.3 Computing a hash with ManagedCryptoAPI
 C# ManagedCryptoAPI l_Crypto = new ManagedCryptoAPI(); IntPtr l_hProvider = l_Crypto.AcquireNamedContext("KICKSTART"); Int32 l_TotalHashBytes = 0; byte[] l_TextBytes =         System.Text.Encoding.ASCII.GetBytes(this.txtTextToHash.Text); byte[] l_HashBytes = l_Crypto.ManagedComputeHash(l_hProvider,         l_TextBytes, ref l_TotalHashBytes); this.txtHashedBytes.Text = ""; for (int i = 0; i < l_TotalHashBytes; i++) {    this.txtHashedBytes.Text += "[" + l_HashBytes[i] + "] "; } VB Dim l_Crypto As ManagedCryptoAPI = New ManagedCryptoAPI Dim l_hProvider As IntPtr = l_Crypto.AcquireNamedContext("KICKSTART") Dim l_TotalHashBytes As Int32 = 0 Dim l_TextBytes() As Byte = System.Text.Encoding.ASCII.GetBytes         (Me.txtTextToHash.Text) Dim l_HashBytes() As Byte = l_Crypto.ManagedComputeHash(l_hProvider,         l_TextBytes, l_TotalHashBytes) Me.txtHashedBytes.Text = "" Dim i As Integer For i = 0 To l_TotalHashBytes - 1    Me.txtHashedBytes.Text += "[" + Convert.ToString(l_HashBytes(i)) + "] " Next i 

Looking Inside ManagedComputeHash

Examining the code inside ManagedComputeHash teaches specifically how to compute a hash through CryptoAPI. ManagedComputeHash will also serve as a case study to observe how ManagedCryptoAPI manipulates the CryptoAPI. The discussion will not drill down into every method in ManagedCryptoAPI , because it would fill the chapter with redundant information. Instead, there is only a drill for computing hashes and encrypting data by using a password. Other parts of the chapter will demonstrate how to perform cryptographic actions with the help of ManagedCryptoAPI without examining the internal actions performed by ManagedCryptoAPI .

To compute the hash for an array of bytes, ManagedComputeHash follows these steps:

  1. ManagedComputeHash creates a buffer large enough to hold the hash data that it will compute.

  2. A new hash object is created by calling CryptCreateHash . CryptCreateHash accepts a handle to a key container in a CSP, returns true if it has succeeded, and returns the handle to a hash object through a reference to an IntPtr . The handle to the key container is passed into ManagedComputeHash . ManagedCryptoAPI uses the CALG_MD5 hash algorithm. The DllImport statement for CryptCreateHash is as follows:

     
     C# [DllImport("coredll.dll")] private static extern bool CryptCreateHash(IntPtr hProv, uint Algid,         IntPtr hKey, uint dwFlags, ref IntPtr phHash); VB Declare Function CryptCreateHash Lib "coredll.dll" (ByVal hProv As         IntPtr, ByVal Algid As Int32, ByVal hKey As IntPtr, ByVal         dwFlags As UInt32, ByRef phHash As IntPtr) As Boolean 
  3. ManagedComputHash calls CryptHashData to hash the input bytes. CryptHashData accepts the handle to the hash algorithm that was derived in step 2. The CryptoAPI computes the hash and retains the resulting hash bytes internally. The DllImport statement for CryptHashData follows:

     
     C# private static extern bool CryptHashData(IntPtr hHash, byte[] pbData,         Int32 dwDataLen, uint dwFlags); VB Declare Function CryptHashData Lib "coredll.dll" (ByVal hHash As         IntPtr, ByVal pbData() As Byte, ByVal dwDataLen As Int32,         ByVal dwFlags As UInt32) As Boolean 
  4. ManagedComputeHash acquires the resulting hash bytes by calling CryptGetHashParam . This is the DllImportStatement for CryptGetHashParam :

     
     C# private static extern bool CryptGetHashParam(IntPtr hHash,         uint dwParam, byte[] pbData, ref Int32 out_NumHashBytes,         uint dwFlags); VB Declare Function CryptGetHashParam Lib "coredll.dll" (ByVal hHash As         IntPtr, ByVal dwParam As UInt32, ByVal pbData() As Byte,         ByRef out_NumHashBytes As Int32, ByVal dwFlags         As UInt32) As Boolean 
  5. The resulting hash bytes are returned to the caller.

Programs can call the CryptHashData function repeatedly before acquiring the resulting hash bytes. Each time CryptHashData is called, the internal hash result is updated to reflect the act of hashing additional data. For example, a program that computes the hash for a large text file could call CryptHashData on each line of text and acquire the resulting hash bytes only after the last line of data has been hashed .

The code for ManagedComputeHash is shown in Listing 14.4.

Listing 14.4 ManagedComputeHash
 C# // Computes a hash of the bytes passed in public byte[] ManagedComputeHash(IntPtr in_hProvider, byte [] in_DataToHash,         ref Int32 out_NumHashBytes) {    byte [] l_HashBuffer = new byte[MAX_HASH];    out_NumHashBytes = (int)MAX_HASH;    try    {       // Step 1: Get a handle to a new hash object that will       // hash the password bytes       IntPtr l_hHash = IntPtr.Zero;       if (!CryptCreateHash(in_hProvider, CALG_MD5, IntPtr.Zero, 0, ref l_hHash))       {          throw new Exception("Could not create a hash object!");       }       // Step 2: hash the password data....       // l_hHash - reference to hash object   in_passwordBytes        // bytes to add to hash       // in_passwordBytes.Length - length of data to compute hash on       // 0 - extra flags       if (!CryptHashData(l_hHash, in_DataToHash, in_DataToHash.Length, 0))       {          throw new Exception("Failure while hashing password bytes!");       }       // Step 3: Retrieve the hash bytes       if (!CryptGetHashParam(l_hHash,  HP_HASHVAL, l_HashBuffer,               ref out_NumHashBytes, 0))       {          throw new Exception("Failure when retrieving hash bytes with                  CryptGetHashParam!");       }    }    finally    {       // Release hash object.       CryptDestroyHash(hHash);    }    return l_HashBuffer; } VB ' Computes a hash of the bytes passed in Public Function ManagedComputeHash(ByVal in_hProvider As IntPtr, ByVal in_         DataToHash() As Byte, ByRef out_NumHashBytes As Int32) As Byte()    Dim l_HashBuffer(Convert.ToInt32(MAX_HASH)) As Byte    out_NumHashBytes = Convert.ToInt32(MAX_HASH)    Try       ' Step 1: Get a handle to a new hash object that will hash the       ' password bytes       Dim l_hHash As IntPtr = IntPtr.Zero       If (CryptCreateHash(in_hProvider, Convert.ToInt32(CALG_MD5),               IntPtr.Zero, Convert.ToUInt32(0), l_hHash) = False) Then          Throw New Exception("Could not create a hash object!")       End If       ' Step 2: hash the password data....       ' l_hHash - reference to hash object   in_passwordBytes - bytes to add to hash       ' in_passwordBytes.Length - length of data to compute hash on       ' 0 - extra flags       If (CryptHashData(l_hHash, in_DataToHash, in_DataToHash.Length,               Convert.ToUInt32(0)) = False) Then          Throw New Exception("Failure while hashing password bytes!")       End If       ' Step 3: Retrieve the hash bytes       If (CryptGetHashParam(l_hHash, HP_HASHVAL, l_HashBuffer, out_               NumHashBytes, Convert.ToUInt32(0)) = False) Then          Throw New Exception("Failure when retrieving hash bytes with                  CryptGetHashParam!")       End If    Finally       ' Release hash object.       CryptDestroyHash(hHash);    End Try    Return l_HashBuffer End Function 

Computing a Hash with a Sample Application

The ComputeHash sample application is located in the folder SampleApplications\Chapter14 . There is a C# and a Visual Basic version. ComputeHash is a stand-alone application that demonstrates how to compute a hash by using the techniques described previously. To use this program, enter text into the textbox labeled Text to Hash and then press the Compute Hash button. A hash for the ASCII encoding of the input bytes is computed and displayed in the Hash Bytes textbox.



Microsoft.NET Compact Framework Kick Start
Microsoft .NET Compact Framework Kick Start
ISBN: 0672325705
EAN: 2147483647
Year: 2003
Pages: 206

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net