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.
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 |
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:
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.
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 |
The ComputeHash sample application is located in the folder SampleApplicationsChapter14. 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.
3.129.24.180