System.Security.Cryptography命名空间中的各个类能够让我们非常容易地为初始数据产生一个哈希值(Hash Value)。在此我们将示范如何产生一个哈希值,以及如何比较两个哈希值以便判断它们是否相同。  
						
							
| 
 《Visual C# 2005文件 IO与数据存取秘诀》节选  | 
| 条款33 | 
 | 
| 条款55 | 
 | 
| 条款56 | 
 | 
| 条款63 | 
 | 
| 条款73 | 
 | 
| 条款100 | 
 | 
| 条款134 | 
 | 
| 条款152 | 
 | 
| 条款161 | 
 | 
| 条款163 | 
 | 
 
 
借助于System.Security.Cryptography命名空间的密码资源,将非常容易产生与比较哈希值。因为所有的哈希函数都接收类型为 Byte() 的输入,因此可能需要将初始数据转换成一个字节数组才能够为它产生哈希值。欲为一个字符串值建立一个哈希值,请依下列步骤进行:
 
1、使用Using语句导入System、System.Security、System.Security.Cryptographic与System.Text命名空间,这样一来,您才不需要于程序代码中编写一长串的完整名称:
 
using System.Drawing;
  using System.Text;
  using System.Windows.Forms;
  using System.Security.Cryptography; 
  | 
 
 
2、声明一个字符串变量来持有您的初始数据,并声明两个字节数组(未定义大小)来持有初始字节与所产生出的哈希值:
 
string sSourceData;
byte[] tmpSource;
byte[] tmpHash;
 
3、使用 GetBytes() 方法(它是System.Text.ASCIIEncoding类的一部分)将您的初始字符串转换至一个字节数组中:
 
sSourceData = "MySourceData"; 
  // 根据初始数据来建立一个字节数组
  tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
 
  | 
 
 
4、通过调用MD5CryptoServiceProvider类的实例的ComputeHash方法来为您的初始数据计算出MD5哈希值。请注意,欲计算出另外一个哈希值,您必须建立该类的另外一个实例。
 
// 根据初始数据计算出哈希值
  tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource); 
  | 
 
 
5、tmpHash字节数组现在会获取您初始数据的哈希值(128位值=16字节)。将此显示或储存成一个十六进制字符串通常会非常有用,下列程序代码即是进行此项处理:
 
lblHashResult.Text = sSourceData + "\n" + ByteArrayToString(tmpHash) + "\n";   private string ByteArrayToString(byte[] arrInput)
  {
  StringBuilder sOutput = new StringBuilder(arrInput.Length); 
  for (int i = 0; i < arrInput.Length; i++)
  {
  sOutput.Append(arrInput[i].ToString("X2"));
  }
 
  return sOutput.ToString();
  }
 
  | 
 
 
6、通过上述程序代码,您便能够为初始数据产生出哈希值并以一个十六进制字符串来表示。接下来,我
们要继续说明如何比较两个哈希值。
 
为初始数据建立哈希值的目的之一,就是要提供一种方式来检查数据是否被更改过,或是不通过实际的值来比较两个值。不论是哪一种情况,您都需要比较两个哈希值。然而,如果两个哈希值皆已储存成十六进制字符串,则比较哈希值的操作将会更加简易。当然,也有可能两个哈希值都是以字节数组的形式存在。
 
后续步骤的程序代码将延续先前步骤的程序代码,以便示范如何比较两个字节数组。
 
7、请在建立一个十六进制字符串的地方,紧接着根据新的初始数据建立一个新的哈希值:
 
sSourceData = "NotMySourceData";
  tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);   byte[] tmpNewHash;
  bool bEqual = false;   tmpNewHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource); 
  | 
 
 
8、比较两个字节数组最直接了当的方式就是通过循环依序处理数组,以便一一比较两数组中的每一个元素。如果有任何元素不相同,或是两数组的大小不相同,则表示两值并不相等:
 
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)
  {
  lblHashResult.Text += "这两个哈希值是相同的";
  }
  else
  {
  lblHashResult.Text += "这两个哈希值并不相同";
  }
 
  | 
 
 
9、保存与运行您的项目,以便查看根据第一个哈希值所建立的十六进制字符串,并确认新的哈希值是否
与初始的相同。
 
完整的程序代码已编写在程序范例CH14_DemoForm008.cs的Load事件处理函数中,请自行参考之。图 14-13所示则是执行结果。
  | 
| 图 14-13 |