Ensuring Data Integrity with Hash Codes

Microsoft Silverlight will reach end of support after October 2021. Learn more.

In Silverlight-based applications, you can use hash codes to help ensure data integrity.

A hash value is a numeric value of a fixed length that uniquely identifies data. Hash values are created with a hashing algorithm derived from the System.Security.Cryptography.HashAlgorithm class. A hashing algorithm is a well-defined mathematical procedure that represents a (potentially) large amount of data as a much smaller integer.

Hash values are also useful for verifying the integrity of data sent through insecure channels. The hash value of received data can be compared to the hash value of data when it was sent to determine whether the data was altered.

Digital signatures often consist of encrypted hash values. Encrypting hash values is an efficient use of computational and bandwidth resources, because hash values represent a large amount of data as a much smaller numeric value. Depending upon your security requirements, you may choose to encrypt a message's hash value instead of encrypting the message itself.

This topic describes how to generate and verify hash codes in Silverlight using the classes in the System.Security.Cryptography namespace. It contains the following sections:

  • Generating a Hash Code

  • Verifying a Hash Code

Generating a Hash Code

The managed hash classes can hash either an array of bytes or a managed stream object. The two examples in this section demonstrate these scenarios.

The following example shows how to use the HMACSHA256 constructor and an IsolatedStorageFileStream object to encrypt an isolated storage file. The key that is used to calculate the hash code is derived using a password that is specified by the user. This code example is part of a larger example provided for the HMACSHA256 class.

' Initialize the keyed hash object.
Dim myhmacsha256 As New HMACSHA256(key)
Dim inStream As IsolatedStorageFileStream = isoStore.OpenFile(sourceFilePath, FileMode.Open)
inStream.Position = 0
' Compute the hash of the input file.
Dim hashValue As Byte() = myhmacsha256.ComputeHash(inStream)
' Reset inStream to the beginning of the file.
inStream.Position = 0
' Write the computed hash value to the output file.
outStream.Write(hashValue, 0, hashValue.Length)
' Copy the contents of the sourceFile to the destFile.
Dim bytesRead As Integer
' read 1K at a time
Dim buffer(1023) As Byte
Do
    ' Read from the wrapping CryptoStream.
    bytesRead = inStream.Read(buffer, 0, 1024)
    outStream.Write(buffer, 0, bytesRead)
Loop While bytesRead > 0
myhmacsha256.Clear()
// Initialize the keyed hash object.
HMACSHA256 myhmacsha256 = new HMACSHA256(key);
IsolatedStorageFileStream inStream = isoStore.OpenFile(sourceFilePath, FileMode.Open);
inStream.Position = 0;
// Compute the hash of the input file.
byte[] hashValue = myhmacsha256.ComputeHash(inStream);
// Reset inStream to the beginning of the file.
inStream.Position = 0;
// Write the computed hash value to the output file.
outStream.Write(hashValue, 0, hashValue.Length);
// Copy the contents of the sourceFile to the destFile.
int bytesRead;
// read 1K at a time
byte[] buffer = new byte[1024];
do
{
    // Read from the wrapping CryptoStream.
    bytesRead = inStream.Read(buffer, 0, 1024);
    outStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
myhmacsha256.Clear();

The following example shows how to use the System.Text.UnicodeEncoding class to convert a string into an array of bytes that can be hashed using one of the hashing algorithms.

Dim HashValue() As Byte
Dim MessageString As String = "This is the original message!"
' Create a new instance of the UnicodeEncoding class to 
' convert the string into an array of Unicode bytes.
Dim UE As New UnicodeEncoding()
' Convert the string into an array of bytes.
Dim MessageBytes As Byte() = UE.GetBytes(MessageString)
' Create a new instance of the SHA1Managed class to create 
' the hash value.
Dim SHhash As New SHA1Managed()
' Create the hash value from the array of bytes.
HashValue = SHhash.ComputeHash(MessageBytes)
byte[] HashValue;
string MessageString = "This is the original message!";
// Create a new instance of the UnicodeEncoding class to 
// convert the string into an array of Unicode bytes.
UnicodeEncoding UE = new UnicodeEncoding();
// Convert the string into an array of bytes.
byte[] MessageBytes = UE.GetBytes(MessageString);
// Create a new instance of the SHA1Managed class to create 
// the hash value.
SHA1Managed SHhash = new SHA1Managed();
// Create the hash value from the array of bytes.
HashValue = SHhash.ComputeHash(MessageBytes);

Verifying a Hash Code

Data can be compared to a hash value to determine its integrity. Usually, data is hashed at a certain time and the hash value is protected in some way. At a later time, the data can be hashed again and compared to the protected value. If the hash values match, the data has not been altered. If the values do not match, the data has been corrupted.

The following example shows how to use the ComputeHash method to validate the signature of an isolated storage file. The key that is used to calculate the hash code is derived from a password that is specified by the user. This code example is part of a larger example provided for the HMACSHA256 class.

' Initialize the keyed hash object. 
Dim hmacsha256 As New HMACSHA256(key)
' Create an array to hold the keyed hash value read from the file.
Dim storedHash(hmacsha256.HashSize / 8 - 1) As Byte
' Create a FileStream for the source file
' Read in the storedHash.
inStream.Read(storedHash, 0, storedHash.Length)
' Compute the hash of the remaining contents of the file.
' The stream is properly positioned at the beginning of the content, 
' immediately after the stored hash value.
Dim computedHash As Byte() = hmacsha256.ComputeHash(inStream)
' compare the computed hash with the stored value
Dim i As Integer
For i = 1 To storedHash.Length - 1
    If computedHash(i) <> storedHash(i) Then
        outputBlock.Text = "Hash values differ! Either wrong password or file has changed."
        Return False
    End If
Next i
outputBlock.Text = "Hash values agree -- no tampering occurred."
// Initialize the keyed hash object. 
HMACSHA256 hmacsha256 = new HMACSHA256(key);
// Create an array to hold the keyed hash value read from the file.
byte[] storedHash = new byte[hmacsha256.HashSize / 8];
// Create a FileStream for the source file
// Read in the storedHash.
inStream.Read(storedHash, 0, storedHash.Length);
// Compute the hash of the remaining contents of the file.
// The stream is properly positioned at the beginning of the content, 
// immediately after the stored hash value.
byte[] computedHash = hmacsha256.ComputeHash(inStream);
// compare the computed hash with the stored value
for (int i = 0; i < storedHash.Length; i++)
{
    if (computedHash[i] != storedHash[i])
    {
        outputBlock.Text = "Hash values differ! Either wrong password or file has changed.";
        return false;
    }
}
outputBlock.Text = "Hash values agree -- no tampering occurred.";