什么是哈希算法
一說到哈希算法, 我瞬間就想到了哈希函數、哈希表, 其實他們並不是一回事.
簡單來說, 哈希算法就是將任意長度的字符串通過計算轉換為固定長度的字符串, 不對, 不光字符串, 應該說是將任意長度的二進制串轉換為固定長度的二進制串, 這個轉換的過程就是哈希算法.
既然將任意長度的字符串轉換成固定長度的, 那么沖突就不可避免了, 比如將0-100所有的數字, 映射到0-10這十個數字上, 難免會發生沖突. 一般來說, 計算得出的哈希值越長, 沖突的概率就越低, 比如說, 計算過后, 哈希值為16個字節, 也就是128位, 那么就有2^128個不同的哈希值, 發生哈希沖突的概率為(1/2)^128, 這個概率可以說很低了.
以MD5為例, 以下是經過MD5轉換后的值:
朋友你好: 677fe16950241e74ef632efb2b9f92a7
朋友你好!: 6efa551df87d9de987f17be4e73eb720
可以看到, 哪怕僅僅差了一個感嘆號, 計算后的值也是天壤之別, 所以很多網站上下載文件的同時還提供md5值, 現在能夠理解了吧, 你將下載后的文件通過md5算法進行計算, 得到的字符串如果和網站給定的不相同, 說明文件被修改過了.
當然, 哈希算法不僅僅只有md5這一種, 以用途來分析哈希算法, 就不說哈希算法的原理了, 因為我不會.
1. 數據校驗
上面說到的md5就是其中的一個, 好像還有一個什么SHA, 不過我不知道, 也就不展開探討了.
md5可以將一個文件經過計算轉換成一個指定長度的字符串, 可以防止文件被篡改, 但是通過加密后的字符串很難逆向推出原文.
前面那個例子可以看到, 即使文件被修改了一點點, 也會導致計算后的值發生很大變換.
2.唯一標識
比如說, 現在有十萬個文件, 給你一個文件, 要你在這十萬個文件中查找是否存在. 一個很笨的辦法就是把每一文件都拿出來, 然后按照二進制串一一進行對比. 但是這個操作注定是比較費時的.
可以用哈希算法對文件進行計算, 然后比較哈希值是否相同. 因為存在哈希沖突的情況, 你可以在相同哈希值的文件再進行二進制串比較.
3.哈希表
在哈希表中使用哈希函數已經並不陌生了, 不再贅述.
4.負載均衡
比如說, 現在又多台服務器, 來了一個請求, 如何確定這個請求應該路由到哪個路由器呢?當然, 必須確保相同的請求經過路由到達同一個服務器. 一種辦法就是保存一張路由關系的表, 比如客戶端IP和服務器編號的映射, 但是如果客戶端很多, 勢必查找的時間會很長. 這時, 可以將客戶端的唯一標識信息(如:IP、username等)進行哈希計算, 然后與服務器個數取模, 得到的就是服務器的編號.
5.分布式存儲
當我們有大量數據時, 一般會選擇將數據存儲到多個服務器, 為了提高讀取與寫入的速度嘛. 決定將文件存儲到哪台服務器, 就可以通過哈希算法取模的操作來得到.
但是, 如果數據多了, 要增加服務器了, 問題就來了, 比如原來是10台服務器, 現在變成15台了, 那么原來哈希值為16的文件被分配到編號6的服務器, 現在被分配到編號1的服務器, 也就意味着所有文件都要重新計算哈希值並重新非陪服務器進行存儲. 一致性哈希就是這個用途, 可以查找我的歷史文章.
暫時我能想到的就只有這些, 當然, 哈希算法的用途還有很多, git中的commit id等, 但是我不太了解, 就假裝沒有吧, 嘿嘿
有時對用戶的密碼進行MD5加密再保存, 確實要比明文保存好的多. 但是, 你以為通過哈希算法進行加密就萬事大吉了么? 不好意思, 並不能, 像前面提到的MD5就已經號稱別破解了.
比如, 你將用戶的密碼進行MD5加密后進行保存, 若有心人拿到你的數據庫數據, 雖然得到的是加密后的密碼, 但是只要准備一個常用密碼的字典, 將字典中的密碼進行加密后與數據庫保存的數據進行比較, 如果相同, 基本上就可以確定了.
我感覺可以對密碼進行雙層加密, 也就是使用兩個不同的加密算法, 一個算法的輸出作為另一個的輸入, 增大一些破解的難度吧.