哈希算法上——如何防止數據庫中的用戶信息被脫庫?

網站是怎麼存儲用戶的密碼這些重要數據的呢,僅僅 MD5 加密一下存儲就夠了嗎?

1. 什麼是哈希算法?

首先,咱們要明確一個概念,不論是 「散列」 仍是 「哈希」,其實都是英文 「Hash」 的中文翻譯,它們實際上是一個意思。算法

所謂哈希算法,其實就是將任意長度的二進制值串映射爲固定長度的二進制值串,這個映射的規則就是哈希算法,而經過原始數據映射以後獲得的二進制值串就是哈希值數據庫

要設計出一個優秀的哈希算法並不容易,通常須要知足如下幾點要求:安全

  • 從哈希值不能反向推導出原始數據(因此哈希算法也叫單向哈希算法);
  • 對輸入數據很是敏感,哪怕原始數據只修改了一個 Bit,最後獲得的哈希值也大不相同;
  • 散列衝突的機率要很小,對於不一樣的原始數據,哈希值相同的機率很是小;
  • 哈希算法的執行效率要儘可能高效,針對較長的文本,也能快速地計算出哈希值。

咱們以 MD5 哈希來驗證一下上面的結論。給出兩個文本 「今天我來說哈希算法」 和 「jiajia」,咱們能夠分別獲得他們的哈希值。 MD5 的哈希值是 128 位的 Bit 長度,這裏咱們將其轉化爲了十六進制編碼。網絡

MD5("今天我來說哈希算法") = bb4767201ad42c74e650c1b6c03d78fa
MD5("jiajia") = cd611a31ea969b908932d44d126d195b

能夠看到,不管要哈希的文本有多長、多短,經過 MD5 哈希以後,獲得的哈希值的長度都是相同的,並且獲得的哈希值看起來像一堆隨機數,徹底沒有規律。數據結構

再來看兩個很是類似的文本, 「我今天講哈希算法!」 和 「我今天講哈希算法」。雖然這兩個文本只有一個感嘆號的區別,但它們的哈希值也是徹底不一樣的。負載均衡

MD5("我今天講哈希算法!") = 425f0d5a917188d2c3c3dc85b5e4f2cb
MD5("我今天講哈希算法 ") = a1fb91ac128e6aa37fe42c663971ac3d

一樣,咱們也很難經過哈希值 「a1fb91ac128e6aa37fe42c663971ac3d」 反推出對應的文本 「我今天講哈希算法」。分佈式

此外,對於很是長的文本,若是哈希算法的計算時間很長,那就只能停留在理論研究的層面,很難應用到實際的軟件開發中。好比,一篇包含 4000 字的文章,用 MD5 計算哈希值,也用不了 1ms 的時間。函數

哈希算法的應用很是多,最多見的有:安全加密、惟一標識、數據校驗、散列函數、負載均衡、數據分片、分佈式存儲等。性能

2. 應用一:安全加密

最經常使用於加密的的哈希算法是 MD5 (MD5 Message-Digest Algorithm,MD5 消息摘要算法)和 SHA (Secure Hash Algorithm,安全散列算法),此外,還有 DES(Data Encryption Standard,數據加密標準)、AES(Advanced Encryption Standard,高級加密標準)。網站

對於用於加密的哈希算法來講,有兩點格外重要。第一點是很難根據哈希值反向推導出原始數據,這正是咱們加密的目的。第二就是散列衝突的機率要很小,然而,實際上,不論是什麼哈希算法,咱們只能作到儘可能減小碰撞衝突的機率,理論上是沒辦法作到徹底不衝突的。

鴿巢原理,也就抽屜原理,就是說,若是有 10 個鴿巢,有 11 只鴿子,那確定有兩個鴿子在同一個鴿巢內。

哈希算法產生的哈希值的長度是固定且有限的,所以,其能表示的數據是有效的,而咱們要哈希的數據是無窮的,就必然會存在哈希值相同的狀況。通常狀況下,哈希值越長的哈希算法,散列衝突的機率越低。

以下這兩段字符串通過 MD5 哈希算法加密以後,產生的哈希值就是相同的。

不過,即使哈希算法存在散列衝突的狀況,可是由於哈希值的範圍很大,衝突的機率極小,因此相對來講仍是很難破解的。

除此以外,沒有絕對安全的加密。越複雜、越難破解的加密算法,須要的計算時間也就越長。咱們在實際的開發中,也須要權衡破解難度和計算時間,來決定究竟使用哪一種加密算法。

3. 應用二:惟一標識

若是要在海量的圖庫中搜索一張圖是否存在,咱們不能單純地用圖片的元信息(好比圖片名稱)來比對,由於有可能存在名稱相同但圖片內容不一樣,或者名稱不一樣而圖片內容相同的狀況。

咱們知道,任何文件在計算中均可以表示成二進制碼串。所以,一種方法就是直接將要查找圖片的二進制碼串與圖庫中全部圖片的二進制碼串一一比對,但這樣的比對顯然很是耗時。

咱們能夠給每個圖片取一個惟一標識,或者說信息摘要。好比,咱們能夠從圖片的二進制碼串開頭取 100 個字節,中間取 100 個字節,結尾再取 100 個字節,而後放在一塊兒經過哈希算法獲得一個哈希值,做爲圖片的惟一標識。經過這個惟一標識來斷定圖片是否在圖庫中,就能夠減小不少工做量。

若是還想繼續提升效率,咱們能夠把每個圖片的惟一標識和相應的圖片文件在圖庫中的路徑信息,都存儲在散列表中。當要查看某個圖片是否是在圖庫中的時候,咱們先經過哈希算法對這個圖片作惟一標識,而後在散列表中查找是否存在這個標識。

若是不存在,說明圖片不在圖庫中;若是存在,咱們再經過散列表中存儲的文件路徑做進一步的對比看是否徹底同樣。若是同樣,就說明圖片已經存在;若是不同,說明兩張圖片儘管惟一標識相同,但並非相同的圖片。

4. 應用三:數據校驗

BT 下載的原理是基於 P2P 協議的,咱們從多個機器上並行下載一個 2GB 的電影,這個電影可能會被分割成不少文件塊(好比 100 塊)。等全部文件塊都下載完成後,再組裝成一個完整的電影文件就好了。

可是,網絡傳輸是不安全的,下載的文件塊多是被宿主機器惡意修改過的,又或者下載過程當中出了錯誤,因此下載的文件塊多是不完整的。若是咱們沒有能力檢測這種惡意修改或者文件下載出錯,就會致使最後合併後的電影沒法觀看,甚至致使電腦中毒。

這時候,咱們能夠經過哈希算法,對 100 個文件分別取哈希值,而且保存在種子文件中。這樣,只要文件塊的內容有一丁點的改變,最後計算出來的哈希值就會徹底不一樣。咱們就能夠經過比對兩次的哈希值來肯定文件是不是徹底正確的。

5. 應用四:散列函數

散列函數是設計一個散列表的關鍵,它直接決定了散列衝突的機率和散列表的性能。不過,相對哈希算法的其餘應用,散列函數對於散列算法衝突的要求要低不少。即使出現個別散列衝突,只要不是過於嚴重,咱們均可以經過開放尋址或者鏈表法來解決。

不只如此,散列函數對於散列算法計算獲得的值,是否能反向解密也並不關心。散列函數中用到的散列算法,更加關注散列後的值可否平均分佈,也就是說,一組數據是否能均勻地散列在各個槽中。

此外,散列函數的快慢,也會影響散列表的性能,因此,散列函數用的散列算法通常都比較簡單,比較追求效率。

6. 解答開篇

存儲網站用戶數據的時候,咱們能夠對用戶密碼加密以後再存儲,不過最好選擇相對安全的加密算法,但僅僅這樣就萬事大吉了嗎?

若是用戶信息被 「脫庫」,黑客雖然拿到的是加密以後的密文,但能夠經過猜的方式來破解密碼,太過簡單的密碼這時候就很容易被猜中。

字典攻擊。咱們須要維護一個經常使用密碼的字典表,把字典中的每一個密碼都用哈希算法計算哈希值,而後拿哈希值和脫庫以後的密文比對。若是相同,基本上就能夠認爲,這個加密以後的密碼對應的明文就是字典中的這個密碼。之因此說基本上能夠認爲,是由於哈希算法有可能存在散列衝突,雖然密文相同,但與之對應的明文可能也不同。

針對字典攻擊,咱們能夠引入一個鹽(salt),跟用戶的密碼組合在一塊兒,增長密碼的複雜度。咱們拿組合以後的字符串來作哈希算法加密,將它存儲到數據庫中,進一步增長破解的難度。不過,安全和攻擊是一種博弈關係,不存在絕對的安全。全部的安全措施,都只是增長攻擊的成本而已。

參考資料-極客時間專欄《數據結構與算法之美》

獲取更多精彩,請關注「seniusen」!

相關文章
相關標籤/搜索