背景
MD5消息摘要算法(英語:MD5 Message-Digest Algorithm)凳忙,一種被廣泛使用的密碼散列函數(shù),可以產(chǎn)生出一個 128 位( 16 字節(jié)草穆,被表示為 32 位十六進制數(shù)字)的散列值(hash value)敢伸,用于確保信息傳輸完整一致遇骑。MD5 由美國密碼學(xué)家羅納德·李維斯特(Ronald Linn Rivest)設(shè)計悯姊,于 1992 年公開羡藐,用以取代 MD4 算法。這套算法的程序在 RFC 1321 中被加以規(guī)范悯许。
將數(shù)據(jù)(如一段文字)運算變?yōu)榱硪还潭ㄩL度值仆嗦,是散列算法的基礎(chǔ)原理。
原理
- 補全消息先壕,在消息尾部瘩扼,先添加一位 1,之后補 0垃僚,使得消息長度(bits) % 512 = 448集绰;
- 然后把消息的長度值模上 2^64, 然后湊齊 64 位拼在尾部谆棺,總長度恰好可以被 512 整除栽燕;
- 初始化 4 個 32 位值,分別為 h0, h1, h2, h3改淑;
- 把消息分割成 k 份碍岔,每份長度 512 位,依次處理這 k 份數(shù)據(jù)朵夏;
- 把 h0, h1, h2, h3 和這 512 為數(shù)據(jù)塊蔼啦,進行 64 輪混淆和擴散處理;
- 拼接 h0, h1, h2, h3 然后輸出侍郭。
注意:MD5 對消息的長度沒有要求询吴。
// 偽代碼
unsigned int32 r[64], k[64]
//移位表
r[ 0..15] := {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22}
r[16..31] := {5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20}
r[32..47] := {4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23}
r[48..63] := {6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21}
//非線性變化掠河,造成雪崩效益
for i from 0 to 63
k[i] := floor(abs(sin(i + 1)) × 2^32)
//初始值
var int h0 := 0x67452301
var int h1 := 0xEFCDAB89
var int h2 := 0x98BADCFE
var int h3 := 0x10325476
//補全消息亮元,首先必須添加一位 1,之后補 0唠摹,使得消息長度(bits) % 512 = 448
//然后把 message 的字節(jié)長度模上 2^64爆捞,以 64 位小端序的方式拼在尾部,總比特位數(shù)恰好可以被 512 整除
append "1" bit to message
append "0" bits until message length in bits ≡ 448 (mod 512)
append original length in bits mod 2^64 as 64-bit little-endian integer to message
//每次處理 512 位
for each 512-bit chunk of message
//512 位每 32 位組成一個值勾拉,共 16 個煮甥,依次存入 w[0..15]
break chunk into sixteen 32-bit little-endian words w[i], 0 ≤ i ≤ 15
var int a := h0
var int b := h1
var int c := h2
var int d := h3
//Main loop:
for i from 0 to 63
if 0 ≤ i ≤ 15 then
f := (b and c) or ((not b) and d)
g := i
else if 16 ≤ i ≤ 31
f := (d and b) or ((not d) and c)
g := (5×i + 1) mod 16
else if 32 ≤ i ≤ 47
f := b xor c xor d
g := (3×i + 5) mod 16
else if 48 ≤ i ≤ 63
f := c xor (b or (not d))
g := (7×i) mod 16
temp := d
d := c
c := b
//非線性變化,造成雪崩效益
b := leftrotate((a + f + k[i] + w[g]),r[i]) + b
a := temp
Next i
//Add this chunk's hash to result so far:
h0 := h0 + a
h1 := h1 + b
h2 := h2 + c
h3 := h3 + d
End ForEach
// 小端序
unsigned int32 digest := h0 append h1 append h2 append h3
字節(jié)的排列方式有兩個通用規(guī)則
- 大端序(Big-Endian)將數(shù)據(jù)的低位字節(jié)存放在內(nèi)存的高位地址藕赞,高位字節(jié)存放在低位地址成肘。這種排列方式與數(shù)據(jù)用字節(jié)表示時的書寫順序一致,符合人類的閱讀習慣斧蜕。
- 小端序(Little-Endian)双霍,將一個多位數(shù)的低位放在較小的地址處,高位放在較大的地址處,則稱小端序洒闸。小端序與人類的閱讀習慣相反染坯,但更符合計算機讀取內(nèi)存的方式,因為CPU讀取內(nèi)存中的數(shù)據(jù)時丘逸,是從低地址向高地址方向進行讀取的单鹿。
比如:存儲 16 進制值 0x12345678,需要使用 4 個字節(jié)深纲,存儲字節(jié)在內(nèi)存地址增長方向分別是
大端序方式存儲:0x12 0x34 0x56 0x78
小端序方式存儲:0x78 0x56 0x34 0x12
安全
1996 年后被證實存在弱點仲锄,可以被加以破解,對于需要高度安全性的資料囤萤,專家一般建議改用其他算法昼窗,如 SHA-2。2004 年涛舍,證實 MD5 算法無法防止碰撞攻擊澄惊,因此不適用于安全性認證,如 SSL 公開密鑰認證或是數(shù)字簽名等用途富雅。
2009 年掸驱,中國科學(xué)院的謝濤和馮登國僅用了 220.96 的碰撞算法復(fù)雜度,破解了 MD5 的碰撞抵抗没佑,該攻擊在普通計算機上運行只需要數(shù)秒鐘毕贼。2011 年,RFC 6151 禁止 MD5 用作密鑰散列消息認證碼蛤奢。
關(guān)于 MD5 的 16 位與 32 位的區(qū)別
MD5 哈希后的位數(shù)一般為兩種鬼癣,16 位與 32 位。16 位實際上是從 32 位字符串中啤贩,取中間的第 9 位到第 24 位的部分待秃。
MD532("123123") = "4297F44B13955235245B2497399D7A93"
MD516("123123") = "13955235245B2497"