我切换站点到轨道上。 这是一个相当大的网站有50K +用户。 问题是,现有的密码散列法是极其微弱的。 我有两个选择:
1)切换到新的算法,生成每个人的随机密码,然后通过电子邮件发送的密码,并立即要求该变更后
2)实施新的算法,但用旧前,然后散列结果。 例如:
密码:ABCDEF =算法1 => xj31ndn =算法2 => $ 21aafadsada214
任何新的密码,将需要经过原始算法(MD5),然后有一个散列的结果如果让任何意义吗? 有没有缺点呢?
我切换站点到轨道上。 这是一个相当大的网站有50K +用户。 问题是,现有的密码散列法是极其微弱的。 我有两个选择:
1)切换到新的算法,生成每个人的随机密码,然后通过电子邮件发送的密码,并立即要求该变更后
2)实施新的算法,但用旧前,然后散列结果。 例如:
密码:ABCDEF =算法1 => xj31ndn =算法2 => $ 21aafadsada214
任何新的密码,将需要经过原始算法(MD5),然后有一个散列的结果如果让任何意义吗? 有没有缺点呢?
通常情况下,没有必要重置密码,一个可以只等到下一次用户登录。
每个密码存储系统必须切换到一个更好的散列算法的选项,你的问题不是一次性的迁移问题。 良好的密码哈希算法,如BCrypt有一个成本因素,从时间到时候你一定要增加这个成本因素(因为更快的硬件的),那么你需要的完全相同的过程,因为你需要进行迁移。
你选择2散列老哈希是一件好事,如果你的第一个算法是非常弱的,你要马上给更多的保护。 在这种情况下,你可以计算出双哈希值,并与新的双哈希数据库取代旧的哈希值。
$newHashToStoreInTheDb = new_hash($oldHashFromDb)
你也应该纪念这个密码散列( 知道为什么 ),这样你就可以将其识别为双哈希值。 这可以在一个单独的数据库字段来实现,也可以包括您自己的签名。 现代密码散列函数还包括算法的签名,让他们可以升级到较新的算法,而且还可以验证旧的哈希值。 该示例示出了BCrypt散列的签名:
$2y$10$nOUIs5kJ7naTuTFkBy1veuK0kSxUFXfuaOKdOKf9xYT0KKIGSJwFa
___
|
signature of hash-algorithm = 2y = BCrypt
验证将运行这样的:
new_hash(old_hash($password))
最简单的解决方案可能是一个“密码哈希类型”列添加到数据库中。 设置它最初的“老”; 当用户使用新的算法,并将数据库类型为“新的”,再哈希登录密码。
这种方法的一个变型是哈希类型存储作为散列字符串的一部分 。 该作品一样好,只要你能明确告诉不同的hash格式分开,并具有的优点是,你还可以包括任何其它需要的参数(如盐和工作因素关键拉伸 )在相同的字符串,不无需添加额外的字段为每个到数据库。
例如,这是通常使用的方式现代化的Unix的crypt(3)实现 (和在各种高级语言,如相应的功能PHP ):一个典型的基于DES(和可怕弱)密码哈希会看起来像abJnggxhB/yWI
,而(略)更现代的哈希可能看起来像$1$z75qouSC$nNVPAk1FTd0yVd62S3sjR1
,其中1
所指定的散列方法, z75qouSC
是盐和nNVPAk1FTd0yVd62S3sjR1
实际哈希,和分隔符$
选择,因为它不能在OLD-出现风格DES哈希值。
你建议的方法,在新的散列计算公式为:
hash = new_hash( old_hash( password ) )
可以在某些情况下非常有用,因为它允许所有现有的记录,而不必等待用户登录进行更新。但是,如果旧的散列函数保留足够的密码熵的只是安全的。
例如,即使一个相当老,弱加密散列函数,如无盐MD5 ,就不够好,因为它的输出取决于整个输入并拥有高达熵,这几乎比任何密码,将会有更多的128位(和以上足以抵御蛮力攻击,反正)。 在另一方面,试图使用旧的基于DES加密中应用这种结构(3)功能作为老哈希将是灾难性的 ,因为旧的crypt(3)将全部忽略,但每个密码的前8个字符(以及即使这些字符是最显著位)。
您可以创建一个新的密码字段已用新密码更新方法,其密码的所有用户,并只与您的选项2更新大家。
与强制密码更新上登录的所有用户使用旧密码方法会自动所有活动用户迁移到新的密码方法相结合这一点。
另一种可能是保留两个哈希值可用于在数据库中单独列迁移阶段:
因此,一段时间后,你将只剩下新的哈希 - 至少在谁至少一次登录的用户。