You want to hash a string to create a unique, repeatable identifier. This can be used to determine if a string has been altered in any way, to identify a password without revealing the actual password, and to convert a string of any length to a unique fixed-length key for cryptographic algorithms.
Sample code folder: Chapter 16\Cryptography
Use the .NET Framework's cryptographic services to generate an industry-standard hash of your data.
A hash is like a one-way encryption. There's no way to recover an original string given its hash value. In fact, it's technically possible for more than one string to return the exact same hash value, although the odds are against this ever happening in the time allotted for the unfolding of the universe. The MD5 hash used in this recipe returns a 16-byte value, and a quick calculation shows there are over 3 x 1038 unique combinations of 16 bytes. If you were to check through all the possible hash patterns at the rate of a million combinations each second, you'd still be quite busy after a few trillion centuries.
The advantage of the MD5 hash is that changing the given string in the minutest way results in a completely different and unique hash value. If you hash a string and get the hash value expected for that string, you can feel very confident that the string has not been altered in any way. A password, for example, can be checked against the original password by comparing the hashes for the original password and the new one. If the hashes match, the passwords match, and you don't even have to know what the passwords are.
The following function isolates the code to generate a hash for a string. This function is part of a module named Crypto that's presented in its entirety in Recipe 16.9:
Public Function GetHash(ByVal plainText As String) As String ' ----- Generate a hash. Return an empty string ' if there are any problems. Dim plainBytes As Byte( ) Dim hashEngine As MD5CryptoServiceProvider Dim hashBytes As Byte( ) Dim hashText As String Try ' ----- Convert the plain text to a byte array. plainBytes = Encoding.UTF8.GetBytes(plainText) ' ----- Select one of the hash engines. hashEngine = New MD5CryptoServiceProvider ' ----- Get the hash of the plain text bytes. hashBytes = hashEngine.ComputeHash(plainBytes) ' ----- Convert the hash bytes to a hexadecimal string. hashText = Replace(BitConverter.ToString(hashBytes), "-", "") Return hashText Catch Return "" End Try End Function
There are several cryptography service providers in the .NET Framework, including SHA1, Triple DES, Rijndael, and others. The MD5 hashing algorithm is a good standard one to use, but you can change the above code to use a different algorithm if desired.
For convenience, this function returns the 16-byte hash converted to a 32-byte hexa-decimal character string. This simplifies tasks such as storing the hash in the registry instead of a password, and it provides a useful way to convert any key string to a 32-byte key for the Rijndael cipher, a technique used in other recipes in this chapter.
The following code demonstrates the GetHash() function by hashing a string and displaying the result, shown in Figure 16-1:
Dim result As New System.Text.StringBuilder Dim workText As String = _ "The important thing is not to stop questioning. " & _ "--Albert Einstein" Dim hash As String = GetHash(workText) result.Append("Plain text: ") result.AppendLine(workText) result.Append("Hash value: ") result.Append(hash) MsgBox(result.ToString( ))
Figure 16-1. Generating an MD5 hash of a string
Recipe 16.9 includes the full source code for the Crypto module.