2013-02-21 70 views
1

我想用PHP安全的用戶密碼存儲在MySQL數據庫。PHP存儲密碼與河豚和鹽胡椒粉

我該如何做得更好?

我的班級:

private static $algo = '$2a'; 
private static $cost = '$10'; 
private static $pepper = 'eMI8MHpEByw/M4c9o7sN3d'; 

public static function generateSalt($length) { 
    $randomBinaryString = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); 
    $randomEncodedString = str_replace('+', '.', base64_encode($randomBinaryString)); 
    return substr($randomEncodedString, 0, $length); 
} 

public static function generateHash($password) { 
    if (!defined('CRYPT_BLOWFISH')) 
     die('The CRYPT_BLOWFISH algorithm is required (PHP 5.3).'); 
    $password = hash_hmac('sha256', $password, self::$pepper, false); 
    return crypt($password, self::$algo . self::$cost . '$' . self::generateSalt(22)); 
} 

public static function checkPassword($hash, $password) { 
    $salt = substr($hash, 0, 29); 
    $password = hash_hmac('sha256', $password, self::$pepper, false); 
    $new_hash = crypt($password, $salt); 
    return ($hash == $new_hash); 
} 
+0

它是這樣的 – 2013-02-21 13:56:18

+0

雖然這在技術上有一個答案,你的問題是相當武斷和開放式的,應該改寫,以解決一個特定的問題,而不是。 – Amelia 2013-02-21 14:06:26

+0

對不起,這是我的第一個「問題」,下次我會變得更好! – veriox 2013-02-21 14:17:15

回答

3

要麼使用this答案的建議(對於PHP> = 5.5),或下面的類。感謝martinstoeckli指出了password_hash函數。我閱讀了代碼,並且在password_hash中我看到的唯一不同的事情是從操作系統的錯誤檢查和DEV_URANDOM用法生成更隨機的鹽。

class PassHash { 
    public static function rand_str($length) { 
     $chars = "./qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"; 
     //only allowed chars in the blowfish salt. 
     $size = strlen($chars); 
     $str = ""; 
     for ($i = 0; $i < $length; $i++) 
      $str .= $chars[rand(0, $size - 1)]; // hello zend and C. 
     return $str; 
    } 
    public static function hash($input) { 
     return crypt($input, "$2y$13$" . self::rand_str(22)); 
     // 2y is an exploit fix, and an improvement over 2a. Only available in 5.4.0+ 
    } 
    public static function hash_weak($input) { 
     return crypt($input, "$2a$13$" . self::rand_str(22)); } 
     // legacy support, Add exception handling and fall back to <= 5.3.0 
    public static function compare($input, $hash) { 
     return (crypt($input, $hash) === $hash); 
    } 
} 

這是我一直使用的。建議也是PHPass。它已經過嘗試和測試。


這個腳本唯一的缺點是我從 rand()生成隨機數,而不是來自操作系統的源,但這很容易改變。

此外,沒有真正的理由在bcrypt上使用SHA256散列。 SHA256很弱,可以用相對小的努力打破。

此外,散列密碼是必要的做法,但對於真正的安全,運行所有的輸入通過至少John the Ripperwordlist,除去最常見的密碼,並告知用戶使用不同的密碼。由於密碼非常脆弱,所以使用Wordlists的效率遠高於任何暴力破解。


而作爲最後一點, 不要強迫用戶使用符號,大寫字母和數字,迫使他們使用長密碼

當涉及到強制密碼時,長度就是一切(沒有幽默意圖)。幾乎任何預設的黑客將被設置爲不超過12個字符,除非配置被編輯。如果您曾經在密碼上看到過「最大長度」的網站,請務必不要在那裏重複使用密碼,因爲它們沒有任何安全性。


1.餅乾的任意選擇;挑你找到最好的工作
2. http://xkcd.com/936/
3相比較(這是幾個數量級的速度更快,在技術上是通過隱藏的安全性)
4.我甚至看到銀行這樣做。密碼的最大長度使我切換銀行。

+0

非常感謝您的好意,我會考慮這個。 – veriox 2013-02-21 14:18:32

+0

@FillipPeyton bcrypt哈希與他們存儲鹽。只需將輸入傳遞給':: Compare()',它可以在我使用過的五個站點中正常工作([示例])(https://github.com/HirotoKun/admin-panel/blob/master/admin /private.php#L93)) - 單獨要求鹽,胡椒粉,哈希和選項都是我沒做過的事情....永遠。 – Amelia 2013-08-01 22:17:26

+0

@FillipPeyton哈希和salt在同一個字符串中。它的形式是$ $ $ '。存儲並比較;它實際上就像'PassHash :: Compare($ password_input,$ hash_from_database); //如果正確,則返回true否則返回false。你正在試圖解決這個問題。 – Amelia 2013-08-01 22:38:19