程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP基礎知識 >> 在php中使用crypt函數的注意事項

在php中使用crypt函數的注意事項

編輯:PHP基礎知識
 

提起crypt,熟悉linux的童鞋肯定想到了用戶密碼保存到/etc/shadow時,就使用了這個函數進行加密。
centos5.8使用的是CRYPT_MD5方式,centos6.2使用的是CRYPT_SHA512方式。

在php開發時,很多系統也會使用crypt來加密用戶密碼,然後保存到mysql中。

下面講幾點使用crypt的注意事項:
1) 一定要使用隨機的salt.
有些人,為了設計和開發上的簡便,整個系統都使用同一個salt。這其實算是一種比較嚴重的錯誤。
可能他們認為,如果使用隨機salt, 那麼salt也肯定要保存到數據庫中, 如果被爆庫,加密後的密碼與salt同時洩露, 使得暴力破解成為可能;與其這樣,還不如讓salt全局唯一,然後保存到php文件中,這樣至少在爆庫後,攻擊者在不知道salt的情況下,無法進行暴力破解。
salt全局唯一的問題在於, 密碼與加密之後的密碼是一一對應的,於是攻擊者可以注冊一個帳號,密碼設置為123456,然後爆庫取得自己加密後的密碼,然後在數據庫中找出所有加密後密碼與此相同的記錄,那麼這些人的密碼肯定也是123456。
更進一步,如果salt由於某種原因被攻擊者得知,那麼他在暴力破解或者字典破解的時候,每一個字典中的密碼,都可以在一次加密之後,同時和數據庫中全部的加密後密碼進行比較, 大大提升了他的破解效率。如果每個人的salt都不同,那每次就只能針對一個用戶進行暴力破解。

2) 使用正確的方法產生隨機salt
生成salt的算法太弱和太強都會有一些問題。
如果太弱,會增加salt重復的概率。
如果太強,比如使用/dev/random來產生大量隨機數,生成速度會相當慢,這樣有可能導致拒絕服務攻擊。
建議使用/dev/urandom,mcrypt_create_iv()或者openssl_random_pseudo_bytes()函數。實在沒辦法了才能使用mt_rand();
在本文的最後,會給出一個使用/dev/urandom生成隨機salt的例子。

3) 選擇正確的cost
在真實服務器上面測試,選擇一個足夠大,但是又不會太慢的cost(CRYPT_BLOWFISH)或者round(CRYPT_SHA256/CRYPT_SHA512)。

4) 選擇正確的php版本。
至少要使用php5.3.7+ ,推薦使用最新的版本,否則crypt可能會不正常。
比如:


var_dump(crypt('foo', '$2a$04$thisisasaltthisisasale$'));
 

在php5.4中會生成:
string(60) “$2a$04$thisisasaltthisisasaleDjUpLNqciaokdZZwyr82a58CUDIz/Se”
而在php5.2中只會生成:
string(13) “$2zJyhpjk3l9E”

5) 選擇正確的prefix

使用CRYPT_BLOWFISH時,推薦使用$2y$,而不是文檔例子中的$2a$

6) 進行錯誤檢查
如果crypt函數出錯,會返回 string(2) “*0″ 或者string(2) “*1″
再考慮到3)中php版本不對的問題, 有必要判斷一下crypt()的返回值是否長度大於13。

7) 使用Library
無論是自己寫一個Library也好,還是使用第三方Library也好,我們目的都是不寫重復的代碼。
推薦:
1. password-compat

https://github.com/ircmaxell/password_compat

2. PasswordLib

https://github.com/ircmaxell/PHP-PasswordLib

3. PHPASS

http://www.openwall.com/phpass/

不過要注意隨時更新這些Library為最新的版本。

8) encode salt

CRYPT_BLOWFISH 的salt為22位,只能包含以下64個字符: ./0-9A-Za-z
而用/dev/urandom生成出來的啥都有,所以需要把它們轉化一下:


$randomSalt = '';

$fp = fopen( '/dev/urandom', 'rb' );
if ( $fp !== FALSE ) {
$randomSalt .= fread( $fp, 32 );
fclose( $fp );
}

if( empty( $randomSalt ) ) exit( 'Unable to generate random number.' );

$salt = substr(strtr(base64_encode($randomSalt), '+', '.'), 0, 22);
 

如果使用了第三方Library,就不必考慮這個問題了。
 

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved