2012-05-20 93 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