密码哈希:使用Keccak还是其他算法
SHA-3哈希算法比赛的获胜者已经选出,获胜的算法是Keccak。
我使用Blowfish算法,并且非常喜欢它,但听说Keccak更好。那我在自己的网站上存储用户密码时,使用它值得吗?
如果值得的话,有没有适用于PHP、Python、Ruby或其他网页编程语言的Keccak实现?
我希望这个问题也能帮助到其他人。谢谢!
3 个回答
这是个老问题,但看起来大家对加密术语又感到困惑了。让我们来理清一些概念。
- Keccak是一种加密哈希函数。
- Blowfish是一种分组密码(它的块大小是64位,现在不应该再用来加密了)。
- Bcrypt是一种密码哈希函数,它的用途和普通的加密哈希函数不同。Bcrypt是基于Blowfish的,但它并不是Blowfish。
我不是在啰嗦,这些区别很重要,因为Keccak并不是和bcrypt竞争,而是和SHA-256竞争。
这里有个简单的方法来安全地存储密码在PHP中:
- 使用
password_hash()
、password_verify()
和password_needs_rehash()
就这么简单。你甚至不需要关心这些函数具体做什么,只需要使用它们(除非你用的是像libsodium这样的东西)。
目前,这个接口提供的是bcrypt。bcrypt大体上是可以的,但有几个小问题需要注意:
- 它会在72个字符后截断密码,这会降低长密码的安全性,因为长密码的每个字符的熵比较低。
- 如果你试图通过预先哈希来绕过上一个问题,要小心不要把原始二进制数据传给bcrypt,因为它在
NUL
字符后也会截断。
如果你担心这些问题,可以暂时使用password_lock作为解决方案。
在PHP 7.2中,可能会通过这个接口使用Argon2i(前提是RFC通过)。
在未来几年(大约PHP 7.5,假设没有重大版本更新),我们可能会看到PASSWORD_ARGON2I
成为PASSWORD_DEFAULT
的新值,但也不一定。我们还有几年时间让加密研究人员对它建立信心。
简短回答:
不行,而且可能永远都不行。对于密码加密,BCrypt 和 PBKDF2-HMAC-xxx 比任何简单的 SHA-1/2/3 算法要好。而且在 SHA-1/2 真的有可行的预映像攻击被公布之前,SHA-3 实际上是最糟糕的选择,特别是因为它的速度快和占用缓存少。
详细回答:
不同密码加密算法相对安全性的一个主要因素是:专门的攻击者在加密密码时能有多快。这就是说,他们用的软硬件组合(专门为密码加密购买的)比你在服务器上用的软件(普通的 C 语言实现)快多少。
SHA-3 的一个主要标准是它应该在嵌入式架构上高效运行,这种架构的特点是缓存和寄存器等资源很少。但这也描述了现代的 GPU:寄存器/累加器少,缓存小;但另一方面,它们的硅片被优化来在大量数据上并行处理同样的任务。这对攻击者的暴力破解尝试来说是完美的:每花一美元在硅片上,攻击者通过购买另一块 GPU 能获得比你购买更好 CPU 时更多的 SHA3 哈希速度。
正因为这个原因,BCrypt 被设计成需要对一个内存表进行更多的读写操作,而这个表的大小目前超过了大多数 GPU 的缓存。这意味着当前基于 GPU 的 BCrypt 实现甚至还赶不上它们的 CPU 版本。所以仅仅选择 BCrypt,就已经让攻击者每花一美元的优势减弱,因为他也得像你一样购买 CPU。
这就是为什么原始速度是密码加密的敌人。你想选择那个最快的软硬件组合能给攻击者带来最小优势的算法。现在,BCrypt 是最佳选择,稍微差一点的选择是 PBKDF2-HMAC-xxx。由于 GPU 可能会在处理 SHA3 上变得更强,我怀疑它会成为正确的选择。我没有 SHA3 的具体数据,但“哪个更安全”并不是一个模糊的相对概念——上面的规则可以用来精确量化它。
我用的是Blowfish,觉得挺好,但听说Keccak更好。
说“更好”其实是个相对的说法。到底在哪方面更好呢?是安全性、性能、可扩展性、还是便携性……?
如果你只是想要更高的“安全性”来加密用户密码,那么Keccak可能不是个好选择。Blowfish在这方面会更好,因为如果有人破解了这个哈希,Blowfish的哈希会更难被暴力破解。
不过,Keccak在一些嵌入式系统上运行得不错,或者如果你需要更好的便携性,它也是个不错的选择。这里有一个在GitHub上的PHP实现,还有另一个实现。你也可以通过下载Keccak源代码来制作自己的语言扩展。
但说实话,最好还是用你熟悉的东西。如果黑客能轻易破解你现在用的Blowfish哈希,那问题就不在于哈希算法,而是在于数据库的访问权限。另外,使用这个PHP扩展的所有服务器都必须安装它,如果你用的是共享主机,这可能会有点麻烦。
实际上,你可能还是继续用你现在的东西比较好。大概率是安全的,而且等Keccak的实现被移植到标准的PHP核心后,你再考虑换也不迟(如果需要的话)。这只是我的一点建议。