认识 PHP 的hash函数
?
Hashing function (散列函式) 在網(wǎng)頁應(yīng)用中被廣泛采用,從數(shù)碼簽署、錯誤檢測、登入驗證、到壓縮儲存空間,由于它的原理比較復(fù)雜,很多人把它跟加密函式混淆,對于如何運用hash function,如何選擇合適的hash function,和它的優(yōu)點缺點都不清楚,本文嘗試解答這些問題。簡單地說,Hashing 是一種數(shù)據(jù)影射(mapping) 的算法(algorithm),通常用來把一大串不定長度的數(shù)據(jù)影射到一個固定長度的、較短的數(shù)據(jù),這個固定長度的數(shù)據(jù)稱為hashing value (散列值)。
例如我們把一個由英文字母組成的任意長度的字串,把每一個字符的ASCII 數(shù)值加起來,最后除以256 得到的余數(shù)作為hash value,這里輸入的字串長度沒有限制,輸出的數(shù)值則必定在0 至255 之間,所以是一個合法的hashing function。
以上的hash function 只有256 個可能的hash value,很明顯有很多字串都會得到相同的hash value,這種情況我們稱為hash collision (散列沖突),或者簡稱collision,事實上從一個不定長度的數(shù)據(jù)影射到一個固定長度的數(shù)據(jù),Collision 是無可避免的,我們并不要求完全沒有collision,只需把collision 的機會盡量降低便可以了,若果真的要完全沒有collision 的話,Hash value 理論上必須與輸入的數(shù)據(jù)長度相同,這樣便違背了hash function 的設(shè)計目的。
現(xiàn)實應(yīng)用的hashing function 通常比較復(fù)雜,比較有名的包括MD4、MD5、SHA1、SHA256 等,它們的hash value 的數(shù)量從2 的幾十次方到幾百次方。其實我們?nèi)魏稳硕伎梢宰孕性O(shè)計一個hashing function,不過基于hashing function 的實際用途,我們對hashing function 有一些基本要求,在進一步解釋前,讓我們看看hashing 有什么常見的用途。
Hashing 的用途
???1.
??????數(shù)碼簽署
??????很多提供程式下載的網(wǎng)站,都會在網(wǎng)頁上列出下載檔案的hash value,比較常見的是MD5 碼,下載的人可以自行計算下載回來的檔案的hash value 是否與網(wǎng)站提供的相符,從而驗證這個程式是否曾經(jīng)被修改,這個過程就是數(shù)碼簽署。數(shù)碼簽署的概念可以應(yīng)用在很多通訊領(lǐng)域,例如你要發(fā)送一個很重要的電子郵件給別人,為了讓收件者放心內(nèi)容在傳送過程中沒有被其他人擅改,你可以另外告訴收件人電子郵件的MD5 碼,讓他自行驗證。
??????在這種用途中,理想的hashing function 應(yīng)該具備兩種特性,首先是任何對原本文件的改動都會令產(chǎn)生的hash value 改變;第二是沒有方法可以得知如何該動原本的文件使計算出來的hash value 相同。
??????當(dāng)然,我們還要確保hash value 不會在傳送途中被人攔截并且修改,但這屬于通訊安全的問題,超越了hash function 的討論。
???2.
??????錯誤檢測
??????資料在網(wǎng)絡(luò)上傳送的時候,會受到很多干擾而使內(nèi)容改變,其中包括網(wǎng)絡(luò)問題、電腦硬件問題、電腦程式問題等,為了檢驗資料的正確性,我們可以一并把資料的hash value 發(fā)送給收件者,讓收件者比對自行計算的hash value 和收到的hash value 來確認資料的正確性。
??????在這種用途種中,理想的hash function 跟上面的要求差不多,就是任何對原本資料的改動都會令產(chǎn)生的hash value 改變。
???3.
??????登入驗證
??????在伺服器上儲存用戶的系統(tǒng)密碼是有風(fēng)險的,第一這樣做等于把密碼的安全交托給伺服器管理員,他們一定可靠嗎?別忘記密碼萬一泄漏背黑鑊的是你而不是他們啊;第二很多用戶把相同的密碼應(yīng)用在很多不同的系統(tǒng)(這樣做當(dāng)然很不好,但你無法限制用戶不可以這樣做),當(dāng)一個系統(tǒng)被黑客入侵泄漏了用戶的密碼,他們在其他系統(tǒng)的帳號也同時中門大開,后果可以很嚴重。為了保障用戶,設(shè)計良好的系統(tǒng)都不會直接儲存用戶的密碼,只會儲存密碼的hash value。用戶登入時輸入的密碼,會被轉(zhuǎn)換成hash value,然后與伺服器上儲存的hash value 比較來進行身分驗證。
??????這種用途的hash function,必須是不可能返過來從hash value 計算原本的密碼。此外,由于collision 的緣故,只要找到一個密碼,它的hash value 與用戶的密碼的hash value 相同,便可以冒認這名用戶登入系統(tǒng),無須知道真正的密碼,所以hash value 的數(shù)量必須非常龐大,使collision 的可能性很低很低,使尋找這個「偽冒」密碼的人要付出很大的代價。
???4.
??????壓縮儲存空間
??????Hash function 其中一個最經(jīng)典的用途是制作hashing table (散列表),它可說是一個關(guān)聯(lián)陣列(associative array),陣列的指標(biāo)是一些不定長度的數(shù)據(jù)或者是比較復(fù)雜的數(shù)據(jù)結(jié)構(gòu),很多高階編程語言包括PHP、Perl、gawk 等都支援關(guān)連陣列,背后的原理就是利用hash function 把這些數(shù)據(jù)轉(zhuǎn)換成數(shù)字,然后讀取陣列中的元素。在大部分的情況下,作為陣列指標(biāo)的數(shù)據(jù)可以非常龐大,但是陣列的長度(元素的數(shù)量) 相對來說卻很少,所以沖突的情況會比較突出,從用戶(編程人員) 的角度沖突是不應(yīng)該發(fā)生的,不同的數(shù)據(jù)便應(yīng)該對應(yīng)到不同的陣列位置,所以這些語言都有某些方法來處理沖突。
??????用hash table 來實作關(guān)聯(lián)陣列的好處是搜索資料的速度高,無論有多少資料,搜索的速度都是固定的,這一點對于要處理大量數(shù)據(jù)的應(yīng)用很重要。
PHP 有什么 hashing 工具?
| Hash Functions | Hash value 的長度 (bit) |
| CRC32 | 32 |
| MD5 | 128 |
| SHA-1 | 160 |
(在PHP5.12以后可以使用 hash_algos()返回所有的hash算法,并從手冊上得知現(xiàn)支持 35種算法;查看手冊)
在PHP5 之前我們只有CRC32、MD5 和SHA1 三個內(nèi)置的hash function,它們輸出的hash value 長度如下:
Hash Functions Hash value 的長度 (bit)
CRC32 32
MD5 128
SHA-1 160
其中SHA-1 可說是最多人使用的hash function,原因是它的hash value 比其他的大,Collision 的機會便小得多。其次SHA 家族的hashing functions 是由美國國家安全部(NSA – National Security Agency) 設(shè)計,并被列為美國聯(lián)邦資訊處理標(biāo)準(zhǔn)的一部分,所以給人較高的信心,很多復(fù)雜的安全方案例如SSL 都使用SHA-1。
PHP 還有兩個需要額外安裝的函式庫支援更多hash function,就是mhash 和hash,Hash 從PHP 5.1.2 開始列為標(biāo)準(zhǔn)的模組,無須自行編譯或安裝,所以越來越多人使用。一些比SHA-1 更先進的hash function 都可以在這兩個函式庫中找到,例如屬于SHA-2 家族的SHA-256 和SHA-512 等,不過由于SHA-1 的歷史比較悠久,很多系統(tǒng)仍然繼續(xù)使用它,尤其是用SHA-1 來進行登入驗證的系統(tǒng),由于hash function 的不可還原性,很難一下子改用其他hash function。
使用SHA-1 的方法很簡單(PHP 的函式大都很簡單,不是嗎?):
echo sha1("I am a happy boy");
Hash 的用法也很簡單:
echo hash("sha256","I am a happy boy.");
Hash 支援很多hash function,可以用hash_algo 查看你的PHP 版本支援什么:
print_r(hash_algos());
總結(jié)
以上是生活随笔為你收集整理的认识 PHP 的hash函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Javascript Tip(1) 操作
- 下一篇: IANA保留地址