2012-05-20 95 views
4

我即將使用這個用戶密碼系統,但我首先要確保我做得正確。這裏是我的測試代碼:我在PHP中正確使用CRYPT_BLOWFISH嗎?

function generateBlowfishSalt() { 
    $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./'; 
    $numChars = strlen($chars); 
    $salt = ''; 

    for($i = 0; $i < 22; ++$i) { 
     $salt .= $chars[mt_rand(0, $numChars - 1)]; 
    } 

    return $salt; 
} 

$password = 'foo'; 
$salt = generateBlowfishSalt(); 
$hash1 = crypt($password, '$2a$12$' . $salt); 
$hash2 = crypt($password, $hash1); 
$compare = ($hash1 == $hash2); 

printf('password: %s</br>', $password); 
printf('salt: %s</br>', $salt); 
printf('hash1: %s</br>', $hash1); 
printf('hash2: %s</br>', $hash2); 
printf('compare: ' . $compare);

下面是一個示例輸出:

password: foo 
salt: MYVJ32OqLcMGBar3pUa.0S 
hash1: $2a$12$MYVJ32OqLcMGBar3pUa.0OTRwv6UX0bcxnSmheKOcqjvqvCrM/p2q 
hash2: $2a$12$MYVJ32OqLcMGBar3pUa.0OTRwv6UX0bcxnSmheKOcqjvqvCrM/p2q 
compare: 1

我的主要問題是:

  1. 我是否正確產生了22字符鹽?我見過的一些實現使用base64_encode()來生成鹽。我需要這樣做嗎?

  2. 將數據庫中的整個$hash1值存儲起來並且不存儲單獨的鹽值是否正確,因爲$hash1將有鹽分,這就是我需要驗證密碼的全部內容嗎?

  3. 在PHP crypt()文檔頁面的CRYPT_BLOWFISH例子有對鹽論證後$(那就是:'$2a$07$usesomesillystringforsalt$')。但在所有的例子中,我看到沒有人使用尾隨$。它是可選的嗎?

感謝

回答

0

你做正確的鹽。只需要隨機。有很多不同的方法可以隨機生成這個。除了約會時間等,有些人使用它。同樣,較長的鹽沒有多大意義,因爲它會被切斷。它需要一定的長度,至少在crypt()方面。所以如果有一點額外的填充讓你感覺更好,那就去吧。

你假設將salt存儲在數據庫中。起初我很難理解。鹽的全部目的只是讓彩虹花費更長的時間,並用密碼列出大量可能的密碼。更正,另外,它也有助於2個或更多相同的密碼,這是必然發生的。如果是這樣,由於隨機鹽,哈希值將會不同。

至於crypt()不斷測試它,直到它看起來和長度相同的PHP PHP的PHP DOC,但是它看起來是正確的。

+0

鹽不是隨機的嗎?我使用mt_rand()來生成它。我認爲我不需要在crypt()返回的值的頂部存儲單獨的salt值,因爲crypt()返回的值幾乎包含了整個鹽值。此外,我只需要第一次調用crypt()以返回值以驗證密碼。 – Ryan

+0

是的,你不需要做任何額外的事情。你正在生成隨機鹽。我很確定我說過「你在正確地做鹽」。只是重申它。你有正確的想法。 – Andy