【问题标题】:Validating passwords with random salts使用随机盐验证密码
【发布时间】:2012-06-05 00:46:50
【问题描述】:

我一直在尝试使用 mysql 数据库了解存储在用户表中的哈希和盐。我完成了存储它们,但似乎无法理解如何验证用户何时登录。
我已经浏览并看到了将盐和哈希分开和一起存储的方法。我生产的盐是随机的。

有什么想法吗?
我已经发布了我的代码。

<?php
$password = 'passwordwhatever';

//generate the salt
function gen_salt() {
    $salt = uniqid(mt_rand(), true) . sha1(uniqid(mt_rand(), true));
    $salt = crypt('sha512', $salt);
    return $salt;
}

//generate the hash
function gen_hash($salt, $password) {
    $hash = $salt . $password;
    for($i = 0; $i < 100000; $i++) {
        $hash = crypt('sha512', $hash);
    }

    $hash = $salt . $hash;
    return $hash;
}

$password = gen_hash(gen_salt(), $password);
echo $password;

?>

【问题讨论】:

  • 盐生成可以以一种不那么矫枉过正的方式完成;只需一个 uniqid(mt_rand(), true) 就足够了,在上面添加一个 sha512 不会让它变得更随机 ;-)

标签: php password-hash


【解决方案1】:

只要您生产相同的盐,就没有太大关系。将其存储在您的数据库中,在配置中,只要您可以访问它。反转 SHA512 哈希的工作量非常大,除非你是五角大楼,否则没人会打扰。关键是您希望能够使用相同的盐重复哈希,这样您就可以非常确定输入是相同的,而不必存储敏感输入。如果这有意义的话。

【讨论】:

  • 正确的钱。我要评论说,你真的不需要花太多精力来加密这样的盐。最重要的是它是随机的,而不是它非常安全。即使有人得到了盐和哈希,专门为该盐创建彩虹表也不是计算上的实际工作。我不会随便把它泄露出去(把它放在后端,不要公开向用户透露),但只是想出一个随机的字母和数字字符串通常就足够安全了。
  • 附注:1)不要为每个密码使用相同的盐;每个盐的每个密码都应该是唯一的。不是字面上唯一的;你不必检查一个不存在或任何东西,只要让它们足够长,这样实际上就几乎没有重复的机会。 2)通常我使用像冒号作为分隔符的哈希值来存储盐。但是,如果您可能想使用它对其他内容进行哈希处理,则可以将其存储在密码表中自己的列中。
【解决方案2】:

盐需要包含在数据库中的某处(或某处)。一些选项是将盐附加到哈希或存储为自己的字段。我喜欢将它附加到哈希中。

$password = $salt . '.' . $hash;

然后,当用户登录时,您获取他的密码,将其分解为哈希和盐,并使用您的密码生成功能(使用密码中的盐而不是随机盐)来确定它是否匹配数据库中的密码。

list($salt,$hash) = explode('.', $password);
$check = gen_hash($salt, $input_pass);
if ($check === $password)
    // valid

【讨论】:

    【解决方案3】:

    也许你应该看看bcryptThis 可能会对您有所帮助。我写了一些tutorials,但它们是德文的。哦,PHP 5.3 原生支持 bcrypt。

    【讨论】: