密碼破解的利器——彩虹表(rainbow table)
目錄:
- 如何儲存密碼才是安全的?
- 彩虹表不是 密碼-->明文 的簡單儲存
- 彩虹表的前身--預先計算的雜湊鏈
- 彩虹表
- 為什麼加鹽雜湊可以抵禦彩虹表
如何儲存密碼才是安全的?
密碼儲存有幾種方式:
- 直接儲存密碼明文m
- 儲存密碼明文的雜湊值hash(m)
- 儲存密碼明文的加鹽雜湊 hash(m+salt),這裡的salt可以是使用者名稱,手機號等,但必須保證每個使用者的salt都不一樣才是安全的。
如果資料庫被入侵。
第一方式,明文儲存,無安全性可言。
第二種方式,雖然是入侵者得到的是hash值,但由於 彩虹表 的存在,也很容易批量還原出密碼明文來。
只有第三種方式才是相對安全的。
彩虹表不是 密碼-->明文 的簡單儲存
要從c=hash(m)逆向得到原始明文m,有三種辦法:
- 暴力破解法:時間成本太高。
- 字典法:提前構建一個“明文->密文”對應關係的一個大型資料庫,破解時通過密文直接反查明文。但儲存一個這樣的資料庫,空間成本是驚人的。
- 構建彩虹表:在字典法的基礎上改進,以時間換空間。是現在破解雜湊常用的辦法。
彩虹表的前身--預先計算的雜湊鏈
既然儲存所有的明文密碼對需要的空間太大,密碼學家們想出了一種以計算時間降低儲存空間的辦法: “預計算的雜湊鏈集”(Precomputed hash chains) 。
這是一條k=2雜湊鏈:

雜湊鏈
H函式就是要破解的雜湊函式。
約簡函式(reduction function) R函式 是構建這條鏈的時候定義的一個函式:它的值域和定義域與H函式相反。通過該函式可以將雜湊值約簡為一個與原文相同格式的值。
這條鏈是這樣生成的:
- 隨機選擇一個明文aaaaaa
- 對其求雜湊得到281DAF40
- R(281DAF40) 得到另外一個明文sgfnyd。
- 繼續重複2,3步驟
儲存的時候,不需要儲存所有的節點,只需要儲存每條鏈的頭尾節點(這裡是aaaaaa和kiebgt)
以大量的隨機明文作為起節點,通過上述步驟計算出雜湊鏈並將終節點進行儲存,可得到一張雜湊鏈集。
預計算的雜湊鏈集的使用
要破解一個hash值,
- 假設其剛好是920ECF10:首先對其進行一次R運算,得到kiebgt,然後發現剛好命中了雜湊鏈集中的(aaaaaa,kiebgt)鏈條。可以確定其極大概率在這個鏈條中。於是從aaaaaa開始重複雜湊鏈的計算過程,發現sgfnyd的雜湊結果剛好是920ECF10,於是破解成功。
- 密文不是“920ECF10”而是“281DAF40”:第一次R運算後的結果並未在末節點中找到,則再重複一次H運算+R運算,這時又得到了末節點中的值“kiebgt”。於是再從頭開始運算,可知aaaaaa剛好可雜湊值為281DAF40。
- 如是重複了k(=2)次之後,仍然沒有在末節點中找到對應的值,則破解失敗。
預計算的雜湊鏈集的意義
對於一個長度為k的預計算的雜湊鏈集,每次破解計算次數不超過k,因此比暴力破解大大節約時間。
每條鏈只儲存起節點和末節點,儲存空間只需約1/k,因而大大節約了空間。
R函式的問題
要發揮預計算的雜湊鏈集的左右,需要一個分佈均勻的R函式。當出現碰撞時,就會出現下面這種情況
111 --H--> EDEDED --R--> 222 --H--> FEDEFE --R--> 333 --H--> FEFEDC --R--> 444
454 --H--> FEDECE --R--> 333 --H--> FEFEDC --R--> 444 -H--> FEGEDC --R--> 555
兩條鏈出現了重疊。這兩條雜湊鏈能解密的明文數量就遠小於理論上的明文數2×k。由於集合只儲存鏈條的首末節點,因此這樣的重複鏈條並不能被迅速地發現。
彩虹表
彩虹表的出現,針對性的解決了R函式導致的鏈重疊問題:
它在各步的運算中,並不使用統一的R函式,而是分別使用R1…Rk共k個不同的R函式(下劃線表示下標)。

彩虹表
這樣一來,及時發生碰撞,通常會是下面的情況:
111 --H--> EDEDED --R1--> 222 --H--> FEDEFE --R2--> 333 --H--> FEFEDC --R3--> 444
454 --H--> FEDECE --R1--> 333 --H--> FEFEDC --R2--> 474 -H--> FERFDC --R3--> 909
即使在極端情況下,兩個鏈條同一序列位置上發生碰撞,導致後續鏈條完全一致,這樣的鏈條也會因為末節點相同而檢測出來,可以丟棄其中一條而不浪費儲存空間。彩虹表的使用
彩虹表的使用比雜湊鏈集稍微麻煩一些。
- 首先,假設要破解的密文位於某一鏈條的k-1位置處,對其進行Rk運算,看是否能夠在末節點中找到對應的值。如果找到,則可以如前所述,使用起節點驗證其正確性。
- 否則,繼續假設密文位於k-2位置處,這時就需要進行Rk-1、H、Rk兩步運算,然後在末節點中查詢結果。
- 如是反覆,最不利條件下需要將密文進行完整的R1、H、…Rk運算後,才能得知密文是否存在於彩虹表之中。
彩虹表中時間、空間的平衡
對於雜湊鏈集, 最大計算次數為k,平均計算次數為k/2
彩虹表的 最大計算次數為1+2+3+……k = k(k-1)/2 ,平均計算次數為[(k+2) * (k +1)]/6。
可見,要解相同個數的明文,彩虹表的代價會高於雜湊鏈集。
無論雜湊鏈集還是彩虹表:
當k越大時,破解時間就越長,但彩虹表所佔用的空間就越小;
相反,k越小時,彩虹表本身就越大,相應的破解時間就越短。
常見的彩虹表和R函式舉例
1)常見的彩虹表: ofollow,noindex">http://project-rainbowcrack.com/table.htm
2)R函式舉例:假設明文為5位數字,則R函式是取雜湊值中前5個數字。參見 https://crypto.stackexchange.com/questions/5900/example-rainbow-table-generation
為什麼加鹽雜湊可以抵禦彩虹表
彩虹表在生成的過程中,針對的是特定的函式H,H如果發生了改變,則已有的彩虹表資料就完全無法使用。
如果每個使用者都用一個不同的鹽值,那麼每個使用者的H函式都不同,則必須要為每個使用者都生成一個不同的彩虹表。大大提高了破解難度。