如何从密码中获取盐并使用它来验证用户?

时间:2014-01-23 20:22:41

标签: php security salt crypt password-hash

我已经阅读了大量关于加密密码的问题和教程,虽然我学到了很多东西,但我找不到答案。

我想使用crypt()来散列我将存储在数据库中的密码。我也知道我需要使用盐才能正常工作,而且我已经读过生成随机盐的最佳方法是使用this或类似的东西。

如果我理解正确的过程是这样的:

  1. 用户输入密码
  2. 随机创建一个盐
  3. 哈希密码和盐
  4. 将结果存储在数据库中
  5. 但是,当用户尝试登录时,如何恢复盐?

    1. 用户输入密码
    2. 我以某种方式添加了他自己独特的随机生成的盐
    3. 将两者混合在一起
    4. 将其与存储在数据库中的哈希盐渍密码进行比较。
    5. 在我发现的几个问题中,其中一个答案是将随机生成的盐存储在数据库中。但我认为盐析的全部目的是为了更加安全,如果攻击者可以访问我的数据库,他会看到“盐”字段,即使我的密码被加密,他也可以轻松访问帐户。

      其他答案表示使用crypt()时,“salt”会被添加到密码前面,因此无需将其存储在单独的字段中。我的问题是,我如何获得它?是否有一些功能可以做到这一点,我完全失踪了?

3 个答案:

答案 0 :(得分:3)

您将salt与散列密码一起存储在数据库中,即hash(salt+password)

如果您的数据库遭到入侵并且某人获得了所有哈希值和盐,他们就无法对您的哈希进行彩虹表攻击 - 他们将需要强制每个哈希值。使用良好的哈希算法,暴力攻击是不可行的。

什么是彩虹表攻击?

让我们假设一个通用的哈希算法,hash(f)

作为攻击者,我预先计算了常用密码(f)及其哈希值(hash(f))。现在,当我得到你的无哈希的哈希数据库时,我只需要在你的数据库中查找与我的预先计算的表(彩虹表)相匹配的哈希值。

例如,如果我的彩虹表存储了f = qwertyhash(f) = someRandomHash的内容,我会通过您的数据库查看someRandomHash并在我找到它时立即查看,我知道用户的密码是qwerty

但是,如果您使用密码保存,当用户将密码设置为qwerty时,您将其哈希计算为hash('saltqwerty),这意味着您没有将其哈希计算为{{1}而是someRandomHash。这使我的彩虹表完全没用。

我别无选择,只能蛮力破桌。我知道盐,但我不知道密码,所以我必须为每个可能的排列和密码组合计算someRandomSaltedHash。使用足够慢的哈希算法,这可能需要几个世纪(最坏的情况)。

您如何登录用户?

用户提交他的user_id和密码。您在数据库中查询该用户的salt。然后计算hash(salt+password)并与存储在数据库中的哈希值进行比较。

答案 1 :(得分:3)

可以在同一个数据库中安全地存储散列密码和盐 - 这个想法是因为盐每次都不同,即使完全相同的密码也会以不同方式存储在数据库中,这实际上消除了与md5编码密码相关的强力查找缺陷。

出于明显的大规模混淆,如果您能够使用PHP v5.5.0或更高版本,则使用password_hashpassword_verify可以非常轻松地进行密码存储。

作为额外的好处,这些函数不要求您在数据库中具有单独的passwordsalt字段 - 您只需存储返回的password_hash值并使用{{ 1}}使用明文密码进行验证。

答案 2 :(得分:0)

我对高级别安全数据库了解不多,但是这个怎么样?:

hashedPassword = hash(UsurID+GivenPassword)

因此,在登录时,首先是用户登录,然后是他的ID,然后是给定的密码,以便与已经在数据库中的hashedPassword进行比较。 正如我所说,我不知道这是否会增加安全性,但至少它会使所有密码不同,不是吗?

无论如何,我还在学习。