Rivest在1989年開發出MD2算法。在這個算法中,首先對信息進行數據補位,使信息的字節長度是16的倍數。然後,以壹個16位的檢驗和追加到信息末尾。並且根據這個新產生的信息計算出散列值。後來,Rogier和Chauvaud發現如果忽略了檢驗和將產生MD2沖突。MD2算法的加密後結果是唯壹的--既沒有重復。
為了加強算法的安全性,Rivest在1990年又開發出MD4算法。MD4算法同樣需要填補信息以確保信息的字節長度加上448後能被512整除(信息字節長度mod 512 = 448)。然後,壹個以64位二進制表示的信息的最初長度被添加進來。信息被處理成512位Damg?rd/Merkle叠代結構的區塊,而且每個區塊要通過三個不同步驟的處理。Den Boer和Bosselaers以及其他人很快的發現了攻擊MD4版本中第壹步和第三步的漏洞。Dobbertin向大家演示了如何利用壹部普通的個人電腦在幾分鐘內找到MD4完整版本中的沖突(這個沖突實際上是壹種漏洞,它將導致對不同的內容進行加密卻可能得到相同的加密後結果)。毫無疑問,MD4就此被淘汰掉了。
盡管MD4算法在安全上有個這麽大的漏洞,但它對在其後才被開發出來的好幾種信息安全加密算法的出現卻有著不可忽視的引導作用。除了MD5以外,其中比較有名的還有SHA-1、RIPE-MD以及HAVAL等。
壹年以後,即1991年,Rivest開發出技術上更為趨近成熟的MD5算法。它在MD4的基礎上增加了"安全-帶子"(Safety-Belts)的概念。雖然MD5比MD4稍微慢壹些,但卻更為安全。這個算法很明顯的由四個和MD4設計有少許不同的步驟組成。在MD5算法中,信息-摘要的大小和填充的必要條件與MD4完全相同。Den Boer和Bosselaers曾發現MD5算法中的假沖突(Pseudo-Collisions),但除此之外就沒有其他被發現的加密後結果了。
Van Oorschot和Wiener曾經考慮過壹個在散列中暴力搜尋沖突的函數(Brute-Force Hash Function),而且他們猜測壹個被設計專門用來搜索MD5沖突的機器(這臺機器在1994年的制造成本大約是壹百萬美元)可以平均每24天就找到壹個沖突。但單從1991年到2001年這10年間,竟沒有出現替代MD5算法的MD6或被叫做其他什麽名字的新算法這壹點,我們就可以看出這個瑕疵並沒有太多的影響MD5的安全性。上面所有這些都不足以成為MD5的在實際應用中的問題。並且,由於MD5算法的使用不需要支付任何版權費用的,所以在壹般的情況下(非絕密應用領域。但即便是應用在絕密領域內,MD5也不失為壹種非常優秀的中間技術),MD5怎麽都應該算得上是非常安全的了。
算法的應用
MD5的典型應用是對壹段信息(Message)產生信息摘要(Message-Digest),以防止被篡改。比如,在UNIX下有很多軟件在下載的時候都有壹個文件名相同,文件擴展名為.md5的文件,在這個文件中通常只有壹行文本,大致結構如:
MD5 (tanajiya.tar.gz) = 0ca175b9c0f726a831d895e269332461
這就是tanajiya.tar.gz文件的數字簽名。MD5將整個文件當作壹個大文本信息,通過其不可逆的字符串變換算法,產生了這個唯壹的MD5信息摘要。如果在以後傳播這個文件的過程中,無論文件的內容發生了任何形式的改變(包括人為修改或者下載過程中線路不穩定引起的傳輸錯誤等),只要妳對這個文件重新計算MD5時就會發現信息摘要不相同,由此可以確定妳得到的只是壹個不正確的文件。如果再有壹個第三方的認證機構,用MD5還可以防止文件作者的"抵賴",這就是所謂的數字簽名應用。
MD5還廣泛用於加密和解密技術上。比如在UNIX系統中用戶的密碼就是以MD5(或其它類似的算法)經加密後存儲在文件系統中。當用戶登錄的時候,系統把用戶輸入的密碼計算成MD5值,然後再去和保存在文件系統中的MD5值進行比較,進而確定輸入的密碼是否正確。通過這樣的步驟,系統在並不知道用戶密碼的明碼的情況下就可以確定用戶登錄系統的合法性。這不但可以避免用戶的密碼被具有系統管理員權限的用戶知道,而且還在壹定程度上增加了密碼被破解的難度。
正是因為這個原因,現在被黑客使用最多的壹種破譯密碼的方法就是壹種被稱為"跑字典"的方法。有兩種方法得到字典,壹種是日常搜集的用做密碼的字符串表,另壹種是用排列組合方法生成的,先用MD5程序計算出這些字典項的MD5值,然後再用目標的MD5值在這個字典中檢索。我們假設密碼的最大長度為8位字節(8 Bytes),同時密碼只能是字母和數字,***26+26+10=62個字符,排列組合出的字典的項數則是P(62,1)+P(62,2)….+P(62,8),那也已經是壹個很天文的數字了,存儲這個字典就需要TB級的磁盤陣列,而且這種方法還有壹個前提,就是能獲得目標賬戶的密碼MD5值的情況下才可以。這種加密技術被廣泛的應用於UNIX系統中,這也是為什麽UNIX系統比壹般操作系統更為堅固壹個重要原因。
算法描述
對MD5算法簡要的敘述可以為:MD5以512位分組來處理輸入的信息,且每壹分組又被劃分為16個32位子分組,經過了壹系列的處理後,算法的輸出由四個32位分組組成,將這四個32位分組級聯後將生成壹個128位散列值。
在MD5算法中,首先需要對信息進行填充,使其字節長度對512求余的結果等於448。因此,信息的字節長度(Bits Length)將被擴展至N*512+448,即N*64+56個字節(Bytes),N為壹個正整數。填充的方法如下,在信息的後面填充壹個1和無數個0,直到滿足上面的條件時才停止用0對信息的填充。然後,在在這個結果後面附加壹個以64位二進制表示的填充前信息長度。經過這兩步的處理,現在的信息字節長度=N*512+448+64=(N+1)*512,即長度恰好是512的整數倍。這樣做的原因是為滿足後面處理中對信息長度的要求。
MD5中有四個32位被稱作鏈接變量(Chaining Variable)的整數參數,他們分別為:A=0x01234567,B=0x89abcdef,C=0xfedcba98,D=0x76543210。
當設置好這四個鏈接變量後,就開始進入算法的四輪循環運算。循環的次數是信息中512位信息分組的數目。
將上面四個鏈接變量復制到另外四個變量中:A到a,B到b,C到c,D到d。
主循環有四輪(MD4只有三輪),每輪循環都很相似。第壹輪進行16次操作。每次操作對a、b、c和d中的其中三個作壹次非線性函數運算,然後將所得結果加上第四個變量,文本的壹個子分組和壹個常數。再將所得結果向右環移壹個不定的數,並加上a、b、c或d中之壹。最後用該結果取代a、b、c或d中之壹。
以壹下是每次操作中用到的四個非線性函數(每輪壹個)。
F(X,Y,Z) =(X&Y)|((~X)&Z)
G(X,Y,Z) =(X&Z)|(Y&(~Z))
H(X,Y,Z) =X^Y^Z
I(X,Y,Z)=Y^(X|(~Z))
(&是與,|是或,~是非,^是異或)
這四個函數的說明:如果X、Y和Z的對應位是獨立和均勻的,那麽結果的每壹位也應是獨立和均勻的。
F是壹個逐位運算的函數。即,如果X,那麽Y,否則Z。函數H是逐位奇偶操作符。
假設Mj表示消息的第j個子分組(從0到15),<<
FF(a,b,c,d,Mj,s,ti)表示a=b+((a+(F(b,c,d)+Mj+ti)<< GG(a,b,c,d,Mj,s,ti)表示a=b+((a+(G(b,c,d)+Mj+ti)<< HH(a,b,c,d,Mj,s,ti)表示a=b+((a+(H(b,c,d)+Mj+ti)<< II(a,b,c,d,Mj,s,ti)表示a=b+((a+(I(b,c,d)+Mj+ti)<<
這四輪(64步)是:
第壹輪
FF(a,b,c,d,M0,7,0xd76aa478)
FF(d,a,b,c,M1,12,0xe8c7b756)
FF(c,d,a,b,M2,17,0x242070db)
FF(b,c,d,a,M3,22,0xc1bdceee)
FF(a,b,c,d,M4,7,0xf57c0faf)
FF(d,a,b,c,M5,12,0x4787c62a)
FF(c,d,a,b,M6,17,0xa8304613)
FF(b,c,d,a,M7,22,0xfd469501)
FF(a,b,c,d,M8,7,0x698098d8)
FF(d,a,b,c,M9,12,0x8b44f7af)
FF(c,d,a,b,M10,17,0xffff5bb1)
FF(b,c,d,a,M11,22,0x895cd7be)
FF(a,b,c,d,M12,7,0x6b901122)
FF(d,a,b,c,M13,12,0xfd987193)
FF(c,d,a,b,M14,17,0xa679438e)
FF(b,c,d,a,M15,22,0x49b40821)
第二輪
GG(a,b,c,d,M1,5,0xf61e2562)
GG(d,a,b,c,M6,9,0xc040b340)
GG(c,d,a,b,M11,14,0x265e5a51)
GG(b,c,d,a,M0,20,0xe9b6c7aa)
GG(a,b,c,d,M5,5,0xd62f105d)
GG(d,a,b,c,M10,9,0x02441453)
GG(c,d,a,b,M15,14,0xd8a1e681)
GG(b,c,d,a,M4,20,0xe7d3fbc8)
GG(a,b,c,d,M9,5,0x21e1cde6)
GG(d,a,b,c,M14,9,0xc33707d6)
GG(c,d,a,b,M3,14,0xf4d50d87)
GG(b,c,d,a,M8,20,0x455a14ed)
GG(a,b,c,d,M13,5,0xa9e3e905)
GG(d,a,b,c,M2,9,0xfcefa3f8)
GG(c,d,a,b,M7,14,0x676f02d9)
GG(b,c,d,a,M12,20,0x8d2a4c8a)
第三輪
HH(a,b,c,d,M5,4,0xfffa3942)
HH(d,a,b,c,M8,11,0x8771f681)
HH(c,d,a,b,M11,16,0x6d9d6122)
HH(b,c,d,a,M14,23,0xfde5380c)
HH(a,b,c,d,M1,4,0xa4beea44)
HH(d,a,b,c,M4,11,0x4bdecfa9)
HH(c,d,a,b,M7,16,0xf6bb4b60)
HH(b,c,d,a,M10,23,0xbebfbc70)
HH(a,b,c,d,M13,4,0x289b7ec6)
HH(d,a,b,c,M0,11,0xeaa127fa)
HH(c,d,a,b,M3,16,0xd4ef3085)
HH(b,c,d,a,M6,23,0x04881d05)
HH(a,b,c,d,M9,4,0xd9d4d039)
HH(d,a,b,c,M12,11,0xe6db99e5)
HH(c,d,a,b,M15,16,0x1fa27cf8)
HH(b,c,d,a,M2,23,0xc4ac5665)
第四輪
II(a,b,c,d,M0,6,0xf4292244)
II(d,a,b,c,M7,10,0x432aff97)
II(c,d,a,b,M14,15,0xab9423a7)
II(b,c,d,a,M5,21,0xfc93a039)
II(a,b,c,d,M12,6,0x655b59c3)
II(d,a,b,c,M3,10,0x8f0ccc92)
II(c,d,a,b,M10,15,0xffeff47d)
II(b,c,d,a,M1,21,0x85845dd1)
II(a,b,c,d,M8,6,0x6fa87e4f)
II(d,a,b,c,M15,10,0xfe2ce6e0)
II(c,d,a,b,M6,15,0xa3014314)
II(b,c,d,a,M13,21,0x4e0811a1)
II(a,b,c,d,M4,6,0xf7537e82)
II(d,a,b,c,M11,10,0xbd3af235)
II(c,d,a,b,M2,15,0x2ad7d2bb)
II(b,c,d,a,M9,21,0xeb86d391)
常數ti可以如下選擇:
在第i步中,ti是4294967296*abs(sin(i))的整數部分,i的單位是弧度。(4294967296等於2的32次方)
所有這些完成之後,將A、B、C、D分別加上a、b、c、d。然後用下壹分組數據繼續運行算法,最後的輸出是A、B、C和D的級聯。
當妳按照我上面所說的方法實現MD5算法以後,妳可以用以下幾個信息對妳做出來的程序作壹個簡單的測試,看看程序有沒有錯誤。
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
d174ab98d277d9f5a5611c2c9f419d9f
MD5 ("123456789012345678901234567890123456789012345678901234567890123456789
01234567890") = 57edf4a22be3c955ac49da2e2107b67a
如果妳用上面的信息分別對妳做的MD5算法實例做測試,最後得出的結論和標準答案完全壹樣,那我就要在這裏象妳道壹聲祝賀了。要知道,我的程序在第壹次編譯成功的時候是沒有得出和上面相同的結果的。
MD5的安全性
MD5相對MD4所作的改進:
1. 增加了第四輪;
2. 每壹步均有唯壹的加法常數;
3. 為減弱第二輪中函數G的對稱性從(X&Y)|(X&Z)|(Y&Z)變為(X&Z)|(Y&(~Z));
4. 第壹步加上了上壹步的結果,這將引起更快的雪崩效應;
5. 改變了第二輪和第三輪中訪問消息子分組的次序,使其更不相似;
6. 近似優化了每壹輪中的循環左移位移量以實現更快的雪崩效應。各輪的位移量互不相同。
MD5源程序
在rfc1321種已經有了用C語言實現MD5算法的源程序,如果妳需要在Java或者像PHP、C#這樣的類C語言上實現的話,只要對那段C代碼作壹些簡單的改動,應該能夠很容易的實現。