一、哈希鏈集
1.哈希鏈的原理
在彩虹表之前,已經出現了對哈希函數的破解算法,被稱爲“預計算的哈希鏈集”(Precomputed hash chains)。當面對要破解的哈希函數H,首先要定義一個函數R,該函數的定義域和值域與哈希函數相反,通過該函數可以將哈希值映射爲一個與原文相同格式的值。需要強調的是,由於哈希函數是不可逆的,所以對於密文進行R運算幾乎不可能得到明文原文。
(1)構造一條哈希鏈
此處k=2
H,R重複次數記爲k,k值應該適當,k太大容易出現重複子鏈,太小存儲空間太大。我們只存儲每條鏈的起點和終點,若干條哈希鏈構成哈希鏈集。
(2)使用哈希鏈破解密文
已知一個密文,假設是y:
(i)對密文進行R運算R(y),將R(y)在終點表中查詢;
若查詢失敗,繼續進行H、R運算,查詢;最多進行K次R運算,要麼查詢成功,要麼破解失敗。
若查詢成功,執行步驟(ii)
(ii)查明文並驗證
由查詢匹配到的終點對應的起點,重複進行H、R運算:起點→m→y=H(m)→R(y)
起點→m→y是查明文過程,y→R(y)是驗證過程。查到明文就是m。
(3)舉例
y=D2A82C9A,R(y)=vfkkd,查表失敗;H(vfkkd)=0CAFC376,R(0CAFC376)=crepa,查表成功。
相應起點終點分別是zhihu、crepa 。
查明文並驗證:
一條哈希鏈代表了k組明文密文對,但它只存儲起點終點,因此相對於暴力表大大節省了空間。哈希鏈破解最耗時的操作就是查詢終點,由於終點數(鏈數)遠遠小於密文數,因此相對於暴力表大大節省了時間。
2.R函數
R函數的選取要求:
(1)將值域限定在固定的範圍之內。事實上,在計算和下載彩虹表時,需要使用不同的庫的。按照不同的哈希函數、字符集、密碼長度 等分爲很多個不同的庫。
(2)儘量保證R的值域均勻分佈,以減少碰撞。
然而實際上很難找到能滿足這些要求的完美的R函數。當計算中發生碰撞時,就會出現如下的子鏈重複的問題:
二、彩虹表
1.彩虹表的構造
爲了解決前面“子鏈重複”的問題,不再使用單一的R函數,而是使用不同的Ri函數(故稱爲彩虹表)。
此處k=3
當兩條鏈發生碰撞的位置不在同一位置時,後續的R函數的不一致使得鏈條的後續部分也不同,從而最大程度地減小了鏈條中的重複子鏈。同時,如果在極端情況下,兩個鏈條有1/k的概率在同一序列位置上發生碰撞,導致後續鏈條完全一致,這樣的鏈條也會因爲末節點相同而檢測出來,可以丟棄其中一條而不浪費存儲空間。
不同的彩虹表使用的R函數集不同。
2.使用彩虹表破解密文
彩虹表的使用比哈希鏈集稍微複雜一些。
已知一個密文,假設是y:
(i)假設密文在k-1位置,對密文進行Rk運算Rk(y),將Rk(y)在終點表中查詢;若查詢成功,執行步驟(ii),若查詢失敗,
假設密文在k-2位置,對密文進行Rk-1、H,Rk運算,將結果Rk(H(Rk-1(y)))在終點表中查詢;若查詢成功,執行步驟(ii),若查詢失敗,
假設密文在k-3位置,......
假設密文在0位置,對密文進行反覆Ri,H運算,將結果在終點表中查詢;若查詢成功,執行步驟(ii),若查詢失敗,破解失敗。
(ii)查明文並驗證
由查詢匹配到的終點對應的起點,重複進行H、R運算:起點→m→y=H(m)→Ri(y)
起點→m→y是查明文過程,y→Ri(y)是驗證過程。查到明文就是m。
舉例:
y=85E4969A
假設密文在2位置:R3(y)查詢失敗;假設密文在1位置:R3(H(R2(y)))查詢失敗;
假設密文在0位置:R3(H(R2(H(R1(y)))))=biqkz查詢成功;
查明文並驗證:明文就是share
3.時空分析
彩虹表減少了沒必要的重複子鏈,相對於哈希鏈集節省了空間;假設鏈長位2k+1(密文k個,明文K+1個),在最壞的情況下即破解失敗的情況下,哈希鏈集進行K次R運算,彩虹表進行1+2+3...+K=k(K+1)/2次R運算,所以彩虹表比哈希鏈集耗時更多。這就是時空的平衡。
三、防禦彩虹表攻擊
1.加鹽
最常用的方法,就是加鹽(salt),實際上相當於改變了哈希函數H的形式。由於彩虹表在構造和破解的過程中,反覆用到了H,H如果發生了改變,則已有的彩虹表數據就完全無法使用,必須針對特定的H重新生成彩虹表,這樣就提高了破解的難度。
2.增加哈希函數H的複雜度
轉自:知乎Smallay