在本文開始,我需要首先從直觀層面闡述雜湊(hash)和加密(encrypt)的區別,因為我見過很多朋友對這兩個概念不是很清晰,容易混淆兩者。而正確區別兩者是正確選擇和使用雜湊與加密的基礎。
概括來說,雜湊(hash)是將目標文字轉換成具有相同長度的、不可逆的雜湊字串(或叫做訊息摘要),而加密(encrypt)是將目標文字轉換成具有不同長度的、可逆的密文。
具體來說,兩者有如下重要區別:
1、雜湊演算法往往被設計成生成具有相同長度的文字,而加密演算法生成的文字長度與明文本身的長度有關。
例如,設我們有兩段文字:「microsoft」和「google」。兩者使用某種雜湊演算法得到的結果分別為:「140864078aeca1c7c35b4beb33c53c34」和「8b36e9207c24c76e6719268e49201d94」,而使用某種加密演算法的到的結果分別為「njdsptpgu」和「hpphmf」。可以看到,雜湊的結果具有相同的長度,而加密的結果則長度不同。實際上,如果使用相同的雜湊演算法,不論你的輸入有多麼長,得到的結果長度是乙個常數,而加密演算法往往與明文的長度成正比。
2.雜湊演算法是不可逆的,而加密演算法是可逆的。
這裡的不可逆有兩層含義,一是「給定乙個雜湊結果r,沒有方法將e轉換成原目標文字s」,二是「給定雜湊結果r,即使知道一段文字s的雜湊結果為r,也不能斷言當初的目標文字就是s」。其實稍微想想就知道,雜湊是不可能可逆的,因為如果可逆,那麼雜湊就是世界上最強悍的壓縮方式了——能將任意大小的檔案壓縮成固定大小。
加密則不同,給定加密後的密文r,存在一種方法可以將r確定的轉換為加密前的明文s。
從數學角度講,雜湊和加密都是乙個對映。下面正式定義兩者:
乙個雜湊演算法r=h
(s)r=h(s)
r=h(s)
是乙個多對一對映,給定目標文字s,h可以將其唯一對映為r,並且對於所有s,r具有相同的長度。由於是多對一對映,所以h不存在逆對映使得r轉換為唯一的s。
有了以上定義,就很清楚為什麼會存在上文提到的兩個區別了。由於雜湊演算法的定義域是乙個無限集合,而值域是乙個有限集合,將無限集合對映到有限集合,根據「鴿籠原理(pigeonhole principle)」,每個雜湊結果都存在無數個可能的目標文字,因此雜湊不是一一對映,是不可逆的。
而加密演算法是一一對映,因此理論上來說是可逆的。
下圖是雜湊和加密過程的圖示:
但是,符合上面兩個定義的對映僅僅可以被叫做雜湊演算法和加密演算法,但未必是好的雜湊和加密,好的雜湊和加密往往需要一些附加條件,下面介紹這些內容。
乙個設計良好的雜湊演算法應該很難從雜湊結果找到雜湊目標文字的碰撞(collision)。那麼什麼是碰撞呢?對於乙個雜湊演算法h,如果s1≠
s2,h
(s1)
=h(s
2)s_1\neq s_2, h(s_1)=h(s_2)
s1=
s2,
h(s1
)=h
(s2
),則s1和s2互為碰撞。關於為什麼好的雜湊需要難以尋找碰撞,在下面講應用的時候會詳解。另外,好的雜湊演算法應該對於輸入的改變極其敏感,即使輸入有很小的改動,如一億個字元變了乙個字元,那麼結果應該截然不同。這就是為什麼雜湊可以用來檢測軟體的完整性。
乙個設計良好的加密演算法應該是乙個「單向陷門函式(trapdoor one-way function)」,單向陷門函式的特點是一般情況下即使知道函式本身也很難將函式的值轉換回函式的自變數,具體到加密也就是說很難從密文得到明文,雖然從理論上這是可行的,而「陷門」是乙個特殊的元素,一旦知道了陷門,則這種逆轉換則非常容易進行,具體到加密演算法,陷門就是金鑰。
順便提一句,在加密中,應該保密的僅僅是明文和金鑰。也就是說我們通常假設攻擊者對加密演算法和密文瞭如指掌,因此加密的安全性應該僅僅依賴於金鑰而不是依賴於假設攻擊者不知道加密演算法。
常用的雜湊衝突解決方法有兩類,開放定址法(open addressing)和鍊錶法(chaining)。
開放定址法是一種解決碰撞的方法,對於開放定址衝突解決方法,比較經典的有線性探測方法(linear probing)、二次探測(quadratic probing)和 雙重雜湊(double hashing)等方法。
當我們往雜湊表中插入資料時,如果某個資料經過雜湊函式雜湊之後,儲存位置已經被占用了,我們就從當前位置開始,依次往後查詢,看是否有空閒位置,直到找到為止。以上圖為例,雜湊表的大小為 8 ,黃色區域表示空閒位置,橙色區域表示已經儲存了資料。目前雜湊表中已經儲存了 4 個元素。此時元素 7777777 經過 hash 演算法之後,被雜湊到位置下標為 7 的位置,但是這個位置已經有資料了,所以就產生了衝突。於是按順序地往後乙個乙個找,看有沒有空閒的位置,此時,運氣很好正巧在下乙個位置就有空閒位置,將其插入,完成了資料儲存。線性探測法乙個很大的弊端就是當雜湊表中插入的資料越來越多時,雜湊衝突發生的可能性就會越來越大,空閒位置會越來越少,線性探測的時間就會越來越久。極端情況下,需要從頭到尾探測整個雜湊表,所以最壞情況下的時間複雜度為 o(n)。
鍊錶法是一種更加常用的雜湊衝突解決辦法,相比開放定址法,它要簡單很多。如下**所示,在雜湊表中,每個位置對應一條鍊錶,所有雜湊值相同的元素都放到相同位置對應的鍊錶中。
murmurhash 是一種非加密型雜湊函式,適用於一般的雜湊檢索操作。已經被應用到很多開源專案如redis,memcached,cassandra,hbase,lucene等。與其它流行的雜湊函式相比,對於規律性較強的key,murmurhash的隨機分布特徵表現更良好。
優缺點如下:
速度快,比安全雜湊演算法快幾十倍;
變化足夠激烈,相似的字串如「abc」和「abd」能夠均勻散落在雜湊環上;
不保證安全性(缺點);
一致性hash演算法小結
把伺服器的ip或者主機名作為key對2 32求餘,餘數一定是2 32 1,然後放到 平行對映 0 2 32次方首尾相連的環上。理想狀態下伺服器會均勻分布在這個環上,當資料儲存時,依然把key對2 32進行求餘,然後分布在hash環上,並且按順時針就近儲存。如果 某乙個節點失效,那麼僅僅會影響 該節點...
hash表 hash演算法
概念 雜湊表 hash table。也叫雜湊表 是依據關鍵碼值 key value 而直接進行訪問的 資料結構。也就是說,它通過把關鍵碼值對映到表中乙個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做雜湊表。給定表m,存在函式f key 對隨意給定的keyword值ke...
hash位址 Hash演算法基礎
hash,一般翻譯做 雜湊 也有直接音譯為 雜湊 的,就是把任意長度的輸入,通過雜湊演算法,變換成固定長度的輸出,該輸出就是雜湊值。這種轉換是一種壓縮對映,也就是,雜湊值的空間通常遠小於輸入的空間,不同的輸入可能會雜湊成相同的輸出,所以不可能從雜湊值來唯一的確定輸入值。簡單的說就是一種將任意長度的訊...