MD5作為一種散列算法,廣泛用於密碼傳輸過程中的“加密”(引號的意思是這並不是真正的加密,而是形成密碼的散列值)過程。MD顧名思義Message Digest(報文摘要),可以將輸入的密碼,一般來說為一個字符串,進行HASH(這里簡稱為加密,其實是報文摘要),並且這個HASH值是單向的,理論上說是不能反向破解(“解密”)的,當然個別網站通過搜集大家簡單的字符串輸入形成所謂的“數據字典”,然后根據大家習慣,進行破解,這個其實就是統計形成的結果,通過比對實現,與MD5算法的理論基礎沒有太大的關系。最近幾年,王小雲教授在研究MD5算法的破解,並且通過一些算法給出破解的方法,也只是理論上的,但僅僅局限於簡單的字符串。所以,目前來說,MD5的算法還是單向的,不可逆推。具體大家可以參考博文:http://www.williamlong.info/archives/1882.html
一般來說,對於未經處理的密碼傳輸,“黑客”有兩種方式獲得你的密碼,一種是傳輸攔截,一種是攻擊服務器,不管哪種都能獲取指定用戶的密碼。通過MD5算法HASH后,即使黑客截取了用戶的密碼,也不能破解(HASH單向)。另外,大家會糾結一個問題,既然MD5算法不能反向破解,也就不能驗證(假設成立),對於密碼HASH來說還有什么作用呢?用戶登錄賬戶一般來說是通過和服務器比對賬戶和密碼來決定是否具有權限登錄的,密碼HASH值保存在服務器數據庫,下次用戶再次輸入密碼就進行HASH值比對就行了。
這樣就遇到一個問題,萬一用戶的密碼丟失了,用戶豈不是找不回原來的密碼?是的,這時候一般的網站做法是用別的途徑進行身份驗證(例如:手機號等),然后進行密碼重置。那為什么網站會提示新密碼不能和原密碼相同,其實這也就是進行密碼HASH值比對的結果。
需要說明的是,MD5算法,更多的用處是形成報文摘要,經私鑰加密后進行數字簽名,這個是公鑰加密體系中的內容,感興趣也可以了解一下。
以下是MD5算法在.NET平台下的實現:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Security.Cryptography; 5 using System.Text; 6 7 namespace MD5Encrypted 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //加密123 14 //MD5網站上給出的加密結果:202cb962ac59075b964b07152d234b70 15 string s = GetMD5("123"); 16 Console.WriteLine("123MD5加密值:" + s); 17 Console.ReadKey(); 18 } 19 public static string GetMD5(string str) 20 { 21 //創建MD5對象 22 MD5 md5 = MD5.Create(); 23 24 //開始加密 25 26 //需要將字符串轉換成字節數組 27 byte[] buffer = Encoding.UTF8.GetBytes(str); 28 29 //返回一個加密好的字節數組 30 byte[] MD5Buffer= md5.ComputeHash(buffer); 31 32 /*字節數組裝換成字符串的三種格式 33 將字節數組中的而每個元素按照指定的編碼格式解析成字符串 34 * 直接將數組toString(); 189 123 645--- 我愛你 35 * 將字節數組中的每個元素toString() . 36 * 37 */ 38 39 40 //將字節數組轉換成字符串 41 //return Encoding.UTF8.GetString(MD5Buffer); 42 43 string strNew = ""; 44 for (int i = 0; i < MD5Buffer.Length; i++) 45 { 46 strNew += MD5Buffer[i].ToString("x2"); //將十進制字符串轉換成16進制 47 } 48 return strNew; 49 } 50 } 51 }
關於以上的代碼需要解釋的幾個地方:
1、關於字節數組轉換成字符串在MD5算法實現過程中會引起的問題。
因為如代碼中所說字節數組轉換成字符串一般有三種形式。然而對於在計算機中存儲的都是二進制,對於一串二進制數可以表示一串漢字、一串英文字符等,那么字節數組的每個字節的解釋就會不一樣,所以這時候要注意。
2、strNew += MD5Buffer[i].ToString("x2");對於該句,toString的用法大家可以查一下API。其中的“x”表示16進制。其中“x”和“x2”的區別就在於,對於0x01,“x”解釋出來的是0x1;而“x2”解釋出來的是0x01;
ToString("X2") 為C#中的字符串格式控制符
X為 十六進制
2為 每次都是兩位數
比如 0x0A ,若沒有2,就只會輸出0xA
假設有兩個數10和26,正常情況十六進制顯示0xA、0x1A,這樣看起來不整齊,為了好看,可以指定"X2",這樣顯示出來就是:0x0A、0x1A。
參考網址:http://www.cnblogs.com/kuang906/articles/2301361.html