【问题标题】:Password hashing: Keccak or not密码哈希:Keccak 与否
【发布时间】:2013-02-08 18:40:48
【问题描述】:

SHA-3 哈希算法竞赛的获胜者已被选中。获胜者的算法是Keccak

我使用 Blowfish 并且非常喜欢它,但据说 Keccak 更好。是否值得将其用于在我的网站上存储用户密码?

如果有,是否有任何用于 Web 编程的 PHP、Python、Ruby 或任何其他语言的 Keccak 实现?

我希望这个问题也能对其他人有所帮助。谢谢!

【问题讨论】:

  • 一旦有了散列算法,就很难切换。您必须同时维护两者,直到所有密码都被转换。这可能永远不会。除非您有充分的理由怀疑您当前的解决方案不够安全,否则我不会担心。
  • 任何反对意见?我在 Google 上搜索并在 Stack Overflow 上搜索了类似的问题。
  • 你真的应该使用像 PBKDF2 这样的现成解决方案,听听 Eli 的回答。您的问题似乎假设哈希算法是可以选择的,但您确实需要一个完整的安全结构。

标签: php python blowfish sha-3 keccak


【解决方案1】:

简短回答:

没有,而且可能永远不会。对于密码哈希,BCrypt 和 PBKDF2-HMAC-xxx 是比任何简单的 SHA-1/2/3 算法更好的选择。在 SHA-1/2 实际发布可行的原像攻击之前,SHA-3 实际上是最差的选择,特别是因为它的速度快且缓存占用少。

更长的答案:

不同密码散列算法的相对安全性的一个主要因素是:与您相比,专门的攻击者散列密码的速度有多快?也就是说,他们的软件/硬件组合(为了密码散列的明确目的而购买)与服务器上的软件(软件的现成 C 实现,为应用程序的需要购买的硬件)相比要快多少。

主要的 SHA-3 标准之一是应该在嵌入式架构上高效运行,这些架构以少量的片上缓存、寄存器等为代表。但这也描述了现代 GPU:更少的寄存器/累加器、更小的片上缓存;但另一方面,他们的芯片经过优化,可以在大量数据上并行执行相同的任务。这对于您的攻击者的蛮力尝试来说是完美的:对于在硅片上花费的每一美元,您的攻击者通过购买另一个 GPU 获得的 SHA3 哈希/秒比购买更好的 CPU 获得的多。

出于这个特定原因,BCrypt 旨在对内存表执行大量读取/写入操作,该内存表目前比大多数 GPU 的缓存还大。这意味着当前基于 GPU 的 BCrypt 实现甚至无法与它们的 CPU 对应。因此,仅通过选择 BCrypt,您就可以通过迫使攻击者购买与您相同的 CPU 来减缓攻击者每花费一美元的优势。

这就是为什么原始速度是密码哈希的敌人。 您想选择一种算法,其最快的软件/硬件组合为您的攻击者提供的每美元优势比您将使用的商品软件/硬件的优势最小。现在,那是 BCrypt,或者 PBKDF2-HMAC-xxx 的选择稍少一些。由于 GPU 可能只会在 SHA3 方面做得更好,我怀疑它永远不会是正确的选择。我没有关于 SHA3 的数字,但“哪个更安全”并不是一个模糊的相对术语——上面的规则可以用来精确量化它。

【讨论】:

  • 这是一个绝妙的答案。我什至没有考虑过,但是@Eli_Collins 很明显,较慢的算法是有利的——尤其是对于密码散列。
【解决方案2】:

这是一个老问题,但听起来大家又被cryptography terminology搞糊涂了。让我们澄清一些事情。

  • Keccak 是一种加密哈希函数。
  • Blowfish 是一种分组密码(块大小为 64 位,不应再用于加密)。
  • Bcrypt 是一个密码散列函数,它的用例与单纯的加密散列函数不同。 Bcrypt 基于 Blowfish,但它不是 Blowfish。

我不只是迂腐;这些区别很重要,因为 Keccak 不是在与 bcrypt 竞争,而是在与 SHA-256 竞争。

这是safely store a password in PHP 的简单方法:

  1. 使用password_hash()password_verify()password_needs_rehash()

就是这样。您甚至不需要关心这些函数的作用,您只需要使用它们(除非您使用的是 libsodium 之类的东西)。

目前该接口提供bcrypt。 Bcrypt 基本没问题,除了一些需要注意的问题:

  1. 它会在 72 个字符后截断密码,这会降低具有低每字符熵密钥空间的长密码的安全性。
  2. 如果您尝试通过预散列来规避前面的脚注,请注意不要将原始二进制文件传递给 bcrypt,因为它还会在 NUL 字符之后截断。

如果您担心这些问题,password_lock 中存在临时权宜之计。

在 PHP 7.2 中,很可能可以通过此接口使用 Argon2i(假设 RFC 通过)。

几年后(大约 PHP 7.5,假设没有主要版本冲突)我们可能会看到 PASSWORD_ARGON2I 成为 PASSWORD_DEFAULT 的新值,但可能不会。我们有几年的时间让密码学研究人员对它充满信心。

【讨论】:

  • 如 #2 中所述,您可以通过预散列、ASCII 编码预散列然后将该 ASCII 字符串发送到 Bcrypt 来克服 Bcrypt 的 72 个字符限制。基本上:password_hash(base64_encode(hash('sha256', $password)), PASSWORD_DEFAULT);
  • @AaronToponce PHP 的hash 默认已经返回一个十六进制编码的字符串,所以你可以省略base64_encode
  • 或者,将true 传递给hash()。使用 base64 编码而不是 hex 编码的原因是您可以在 72 字符截断之前拟合更多可能的值,但是 SHA256 哈希具有比任何人都能够迭代的更多可能的值,更不用说尝试 bcrypt 哈希了。
【解决方案3】:

I use Blowfish and really like it, but Keccak is said to be better.

“更好”是一个相对的术语。在什么方面更好?安全性、性能、可扩展性、可移植性……?

如果您只想为散列用户密码提供更高的“安全性”,那么 Keccak 可能是一个不是的好选择。 Blowfish 将为您提供更好的“安全性”,因为如果发现散列,则暴力破解散列将花费更长的时间。

话虽如此,如果您正在寻找在嵌入式架构上运行的东西,或者如果您想要更大的可移植性,Keccak 是一个不错的选择。 Here is a PHP implementation on githubhere is another 您也可以通过downloading the Keccak source 制作自己的语言扩展。

但是,老实说,最好还是坚持你所知道的。如果黑客可以轻松获取您当前使用的河豚散列,那么问题不在于散列算法,而在于对数据库的访问。另请注意,PHP 扩展必须安装在所有使用它的服务器上,如果您使用的是共享主机,这可能会也可能不会。

实际上,您可能应该坚持现有的。很有可能它足够安全,一旦 Keccak 实现被移植到标准 PHP 核心,您就可以移动(如果需要)。只是我的两分钱。

【讨论】:

  • 对不起,这个旧的公认答案是错误的,并且可能具有误导性。 Keccak 是一个非常快的哈希,这意味着它可以被暴力破解——攻击者可以在合理的计算时间内测试所有候选明文密码。请参阅有关密码存储的规范答案:security.stackexchange.com/questions/211/…
  • 同意这个答案是错误的和误导性的 - 请参阅这个一般性答案,它也适用于 SHA-3 和任何其他不专门用于密码散列的散列算法:stackoverflow.com/questions/401656/…
  • 投了反对票,因为这个答案肯定是错误的和误导性的。 Eli Collins 的另一个答案是正确答案。密码散列应该始终与专用的密码散列算法和适当的成本因素一起使用。在 2016 年,这是 Argon2、scrypt、bcrypt、sha512crypt、sha256crypt 或 PBKDF2。威胁模型是具有高度并行化 GPU、FPGA 和 ASIC 的密码破解者。使用通用散列函数,无论@sellibitze 的解决方案多么有创意,总是错误的。
  • @AaronToponce 大多数 ad-hoc 迭代方案并不比 PBKDF2 和 sha2crypt 差,也没有那么难看(尽管 @.sellibitze 忘记了盐)。另一方面,Bcrypt&co 比任何迭代的通用哈希都要好。
  • Blowfish 是个不错的选择,bcrypt(简称CRYPT_BLOWFISH)是个不错的选择。不同的算法。
猜你喜欢
  • 2015-05-27
  • 2014-10-21
  • 2013-05-19
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 2011-06-20
  • 2023-04-08
  • 2015-11-30
相关资源
最近更新 更多