我们有一个使用MS会员提供商存储密码的遗留系统,并且刚刚发现它只使用带有随机盐的SHA1来存储密码,所以显然我们担心这种情况。我知道理想的情况是强制重置全局密码,但出于各种原因,我们希望尽可能避免这种情况,并保持现有密码不变。我已经做了一些探索,并设法找到一些源代码,并可以重新哈希我的密码,所以我得到与它的存储版本相同的结果,所以我想要覆盖所有适当的方法来重新实现以安全的方式编码。
我建议做的是使用当前“安全”哈希重新存储存储的密码(AFAIK,由于强制密码所需的计算时间,目前的方法仅被归类为安全密码,因此如果系统获得大的性能升级,整个编程世界可能最终不得不重新考虑这个),然后将这个哈希值包装在代码中的现有哈希值中,但我有两个问题: -
这实际上是安全的吗?据我所知,每个哈希需要增加熵量,我90%肯定会这样做,但是这样做有什么问题我需要注意吗?我也猜测,在哈希链中,它是确定“基线”安全级别的最强哈希函数,但我想我会仔细检查没有任何奇怪的数学怪癖,哈希是一个“不安全”哈希。我肯定不会,但由于问题的性质,我宁愿问一个愚蠢的问题而不是做出任何不正确的假设,因为哈希函数的技术方面不是我真正研究的东西。
在重新散列之前,我是否应该将盐重新应用于当前哈希值。我对此的想法是,如果有现有的计算表将旧的哈希值转换为较新的哈希值 - 以防有人狡猾地做了咕噜声试图绕过这种方法。我相信b-crypt可能已经包含了一个盐,但是如果我使用的是替代品,我猜我应该包括一个?
答案 0 :(得分:1)
如果您不能等待下次用户登录并且不想强制登录,则双重哈希可以是立即保护非常弱的密码哈希的好方法。弱密码哈希包括无盐哈希或非常快速的哈希,如SHA - * / MD5。
所以你可以这样准备你的数据库:
oldSalt
来验证双重哈希值。newHash = newSafeHashFunction(oldHash, newSalt)
中。现在安全散列函数是BCrypt,SCrypt,Argon2和PBKDF2。生成一个满足新密码哈希函数要求的新盐。newSafeHashFunction(password, newSalt)
替换双哈希。大多数密码哈希实现会自己生成一个安全的盐,并将其包含在生成的密码哈希字符串中,因此不需要单独生成和存储它们。当用户下次登录时,可以像这样验证密码:
if (checkIfDoubleHash(storedHash))
correctPassword = newSafeHashFunction(oldUnsafeHashFunction(password, oldSalt), storedHash)
else
correctPassword = newSafeHashFunction(password, storedHash)
➽注意函数checkIfDoubleHash()
,它是至关重要的,也是双重散列的常见缺陷。如果我们通常接受newSafeHashFunction(password, storedHash)
并且攻击者可以获得旧备份,或者具有早期SQL注入的值,则他可以直接使用旧哈希作为密码。
checkIfDoubleHash()
的实现可以像检查旧盐一样简单,或者可以在将哈希标记为双哈希时将其作为未来证明。大多数框架已经提供了password_hash()
函数,它添加了这样一个“标记”,因此他们可以在必要时切换到更新的算法。
$2y$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
|
hash-algorithm-descriptor = 2y = BCrypt
这是Unix crypt()函数常用的格式。没有什么可以阻止您使用自己的描述符进行双哈希。当然,标记也可以存储在单独的数据库字段中。