我已经阅读了大量关于加密密码的问题和教程,虽然我学到了很多东西,但我找不到答案。
我想使用crypt()来散列我将存储在数据库中的密码。我也知道我需要使用盐才能正常工作,而且我已经读过生成随机盐的最佳方法是使用this或类似的东西。
如果我理解正确的过程是这样的:
但是,当用户尝试登录时,如何恢复盐?
在我发现的几个问题中,其中一个答案是将随机生成的盐存储在数据库中。但我认为盐析的全部目的是为了更加安全,如果攻击者可以访问我的数据库,他会看到“盐”字段,即使我的密码被加密,他也可以轻松访问帐户。
其他答案表示使用crypt()时,“salt”会被添加到密码前面,因此无需将其存储在单独的字段中。我的问题是,我如何获得它?是否有一些功能可以做到这一点,我完全失踪了?
答案 0 :(得分:3)
您将salt与散列密码一起存储在数据库中,即hash(salt+password)
。
如果您的数据库遭到入侵并且某人获得了所有哈希值和盐,他们就无法对您的哈希进行彩虹表攻击 - 他们将需要强制每个哈希值。使用良好的哈希算法,暴力攻击是不可行的。
什么是彩虹表攻击?
让我们假设一个通用的哈希算法,hash(f)
。
作为攻击者,我预先计算了常用密码(f
)及其哈希值(hash(f)
)。现在,当我得到你的无哈希的哈希数据库时,我只需要在你的数据库中查找与我的预先计算的表(彩虹表)相匹配的哈希值。
例如,如果我的彩虹表存储了f = qwerty
,hash(f) = someRandomHash
的内容,我会通过您的数据库查看someRandomHash
并在我找到它时立即查看,我知道用户的密码是qwerty
。
但是,如果您使用密码保存,当用户将密码设置为qwerty
时,您将其哈希计算为hash('saltqwerty
),这意味着您没有将其哈希计算为{{1}而是someRandomHash
。这使我的彩虹表完全没用。
我别无选择,只能蛮力破桌。我知道盐,但我不知道密码,所以我必须为每个可能的排列和密码组合计算someRandomSaltedHash
。使用足够慢的哈希算法,这可能需要几个世纪(最坏的情况)。
您如何登录用户?
用户提交他的user_id和密码。您在数据库中查询该用户的salt。然后计算hash(salt+password)
并与存储在数据库中的哈希值进行比较。
答案 1 :(得分:3)
你可以在同一个数据库中安全地存储散列密码和盐 - 这个想法是因为盐每次都不同,即使完全相同的密码也会以不同方式存储在数据库中,这实际上消除了与md5
编码密码相关的强力查找缺陷。
出于明显的大规模混淆,如果您能够使用PHP v5.5.0
或更高版本,则使用password_hash
和password_verify
可以非常轻松地进行密码存储。
作为额外的好处,这些函数不要求您在数据库中具有单独的password
和salt
字段 - 您只需存储返回的password_hash
值并使用{{ 1}}使用明文密码进行验证。
答案 2 :(得分:0)
我对高级别安全数据库了解不多,但是这个怎么样?:
hashedPassword = hash(UsurID+GivenPassword)
因此,在登录时,首先是用户登录,然后是他的ID,然后是给定的密码,以便与已经在数据库中的hashedPassword进行比较。 正如我所说,我不知道这是否会增加安全性,但至少它会使所有密码不同,不是吗?
无论如何,我还在学习。