目標是要得到一個檔案的32位十六進位表示的MD5值,如同用WinMD5軟體計算出來的結果一樣。
.net提供的計算MD5值的類是位於System.Security.Cryptography命名空間下的MD5CryptoServiceProvider類。我使用其中的提供Stream對象作為參數的ComputeHash重載方法計算指定檔案的MD5值。代碼如下:
using System;
using System.IO;
using System.Security.Cryptography;
class App
{
static void Main()
{
string path = @"d:/temp.txt";
FileStream fs = new FileStream(path,FileMode.Open,FileAccess.Read);
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte [] md5byte = md5.ComputeHash(fs);
foreach (byte b in md5byte)
{
Console.Write(Convert.ToString(b,16));
}
Console.ReadLine();
}
}
這樣就可以顯示出該檔案的MD5值了。
但是這樣有個問題,就是結果不一定總是32位的。原因就是使用Convert.ToString()方法在轉換的時候,不會將類似0x2這樣的數字轉換成0x0和0x2兩個位元組,導致最後的結果少於32位,也就跟用WinMD5計算的結果不一致了。所以我還得手動將每一個位元組拆分成兩個位元組,並轉換成十六進位的字串表示。方法就是對每一個位元組,分別左移和右移四位,得到兩個數,然後再分別轉換成一個位元組表示的十六進位(不知道誰有更先進的辦法)。這樣得到的結果就跟用WinMD5計算得到的結果一致了,完整代碼如下:
using System;
using System.IO;
using System.Security.Cryptography;
class App
{
static void Main()
{
string path = @"d:/temp.txt";
FileStream fs = new FileStream(path,FileMode.Open,FileAccess.Read);
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte [] md5byte = md5.ComputeHash(fs);
int i,j;
foreach (byte b in md5byte)
{
i = Convert.ToInt32(b);
j = i >> 4;
Console.Write(Convert.ToString(j,16));
j = ((i << 4) & 0x00ff) >> 4;
Console.Write(Convert.ToString(j,16));
}
Console.ReadLine();
}
}
簡單解釋一下其中的關鍵區段:
j = i >> 4,是將高四位提取出來,得到和原始數高四位等值的一個數
i << 4是左移四位,但是高四位仍然存在,所以就和0x00ff按位與來去掉高四位,再把結果右移四位就得到了和原始數低四位等值的一個數了
這樣就將一個位元組拆分成了高四位和低四位兩個數了。
比較麻煩的就是獲得低四位,而這其中的關鍵就是左移後高位元仍然存在,我開始不知道怎麼辦,後來問了一個網友才知道可以通過和0x00ff按位與來解決這個問題的