密码哈希 - 如何升级?

Ans*_*Kao 27 security authentication passwords hash database-design

关于最佳算法的讨论很多- 但如果你已经在制作中呢?如何升级而无需重置用户?


编辑/免责声明:虽然我最初想要一个"快速修复"解决方案,并选择了orip的回复,但我必须承认,如果您的应用程序中的安全性非常重要,甚至无法解决这个问题,那么快速修复是错误的心态和他的建议解决方案可能不充分.

Jon*_*eet 24

一种选择是使存储的哈希包含算法版本号 - 因此您从算法0(例如MD5)开始并存储

0:ab0123fe
Run Code Online (Sandbox Code Playgroud)

然后当您升级到SHA-1时,将版本号更改为1:

1:babababa192df1312
Run Code Online (Sandbox Code Playgroud)

(不,我知道这些长度可能不对).

这样,您可以随时确定在验证密码时要检查的版本.您可以通过擦除以该版本号开头的存储哈希值来使旧算法无效.

如果您已经在没有版本号的情况下生成哈希,只需选择一个方案,以便您可以轻松识别未版本化的哈希 - 例如,使用上面的冒号方案,任何不包含冒号的哈希必须按定义在版本控制方案之前,因此可以推断为版本0(或其他).

  • 我的第一个想法是将哈希版本号存储在自己的字段中.没有修辞:为什么要把它包含在字符串中? (6认同)
  • @Matchu它几乎是一样的,但你是对的,将它存储在一个单独的字段中会使查询表更容易,看看有多少用户已经升级 (4认同)
  • @Matchu:由于一个没有另一个是无用的,将它们存储在同一个字段中可确保您永远不会遇到有一个而不是另一个的情况. (2认同)

ori*_*rip 20

保护所有现有密码的一种很酷的方法:使用现有的哈希作为新密码哈希的输入.

因此,如果您现有的哈希值是直接的MD5,并且您计划转移到某种形式的PBKDF2(或bcryptscrypt),那么请将您的密码哈希值更改为:

PBKDF2( MD5( password ) )
Run Code Online (Sandbox Code Playgroud)

您已经在数据库中拥有MD5,所以您只需将PBKDF2应用于它.

这种方法运行良好的原因是MD5与其他哈希(例如SHA-*)的弱点不会影响密码使用.例如,它的冲突漏洞对于数字签名是毁灭性的,但它们不会影响密码哈希.与较长的哈希相比,MD5通过其128位输出稍微减少了哈希搜索空间,但与密码搜索空间本身相比,这是微不足道的.

密码散列强大的原因是减慢(通过迭代在PBKDF2中实现)和随机的,足够长的盐 - 初始MD5不会对它们中的任何一个产生负面影响.

当你正在使用它时,也要在密码中添加一个版本字段.

编辑:加密StackExchange 对此方法进行了有趣的讨论.

  • @MicE - 针对暴力攻击的安全性与其最薄弱的链接一样强大 - 在这种情况下是密码本身,而不是哈希.密码的范围远小于哈希的范围,并且重新划分 - 虽然理论上失去了一些范围 - 但相比之下微不足道.事实上,内部PBKDF2重新散列密码数千次或更多次.例如,要在密码中获得相当于128位的熵,您需要一个包含所有可用键盘字符的20个字符的完全随机密码,包括所有特殊字符. (4认同)

Set*_*eth 9

等到用户登录(因此您有明文密码),然后使用新算法对其进行哈希并将其保存在数据库中.