尝试哈希密码,但每次只是哈希到* 0

时间:2015-07-17 18:26:10

标签: php database security encryption blowfish

我出于明显的安全原因,学习如何使用PHP散列密码。我有以下两个用于设置和检查哈希的函数:

function password_encrypt($password)
{
    $hash_format = "$2y$10$"; //blowfish
    $salt_length = 22;
    $unique_random_string = md5(uniqid(mt_rand(), true));
    $base64_string = base64_encode($unique_random_string);
    $modified_base_64_string = str_replace('+', '.', $base64_string);
    $salt = substr($modified_base64_string, 0, $length);
    $format_and_salt = $hash_format . $salt;
    $hash = crypt($password, $format_and_salt);
    echo $hash;
    return $hash;
}

function password_check($password, $existing_hash)
{
    $hash = crypt($password, $existing_hash);
    if($hash === $existing_hash)
    {
        return true;
    }
    else
    {
        return false;
    }
}

我的问题是每次我散列密码并将其发送到数据库时,它只会被存储为* 0。我不知道* 0来自哪里。我正在做什么有什么问题吗?

基本上当我使用它时,我只需从$ _POST中获取输入的密码,然后使用password_encrypt()对其进行加密。但似乎它总是以* 0出现在另一边。

1 个答案:

答案 0 :(得分:4)

简短而正确的答案

不要使用自己的加密技术,使用已经过安全专家审查的实现。对于PHP 5.5及更高版本,这意味着password_hash()password_verify()。对于早期版本的PHP,您可以使用password_compat(如果您的PHP版本低于5.4,那么运行不受支持的PHP版本会让您感到羞耻。)

Crypto Self-Education答案

如果您已经开始编写自己的加密代码(用于学习体验等),则必须承诺永远不会部署未经验证的实现,并为安全起见依赖它。否则,只需使用password_hash()password_verify()并立即停止阅读。

您的代码存在很多问题。让我们系统地从password_encrypt()开始。 (顺便说一下,你没有加密密码,你正在对它进行哈希处理。)

$unique_random_string = md5(uniqid(mt_rand(), true));

是的,。这不是为bcrypt哈希生成salt的加密安全方法。您应该看一下password_compat如何实现此功能。或者,查看random_compat如何为加密目的生成随机字节。 (另外,请告诉任何人建议你使用那个单行代码生成他们正在玩火的随机字符串。)

$unique_random_string = random_bytes(17);

继续......

$modified_base_64_string = str_replace('+', '.', $base64_string);
$salt = substr($modified_base64_string, 0, $length);

您忘记了第二个变量名称中的下划线。此外,没有名为$length的变量。这些修正后的行看起来像这样:

$modified_base_64_string = str_replace('+', '.', $base64_string);
$salt = substr($modified_base_64_string, 0, $salt_length);

接下来,

$hash = crypt($password, $format_and_salt);
echo $hash;
return $hash;

请不要在示例代码中留下echo语句。此外,您应该检查错误并抛出异常,这样如果bcrypt散列失败,您的应用程序就不会快乐。

$hash = crypt($password, $format_and_salt);
if ($hash === '*0') {
    throw new Exception('Password hashing unsuccessful.');
}
return $hash;

哇,差不多完成了。我们现在来看看你的password_check()函数:

if($hash === $existing_hash)
{
    return true;
}
else
{
    return false;
}

请勿使用=====比较加密输出(密码哈希值,MAC等),否则请将timing attacks邀请到您的应用程序中。对PHP 5.6或hash_equals()使用a hash_equals() polyfill for earlier versions of PHP

return hash_equals($hash, $existing_hash);

我希望这是一次教育经历。密码学很难,不要重新发明轮子。