8

我的问题来自 如何用河豚散列长密码(> 72个字符)

我正在使用 bcrypt(blowfish) 对密码进行哈希处理。所以,正如我从这个问题中发现的那样 https://security.stackexchange.com/questions/39849/does-bcrypt-have-a-maximum-password-length

它的字符数限制为 72。

所以,我开始考虑限制密码的最大长度,但是在这些问题和他们的答案之后

https://security.stackexchange.com/questions/33470/what-technical-reasons-are-there-to-have-low-maximum-password-lengths

为什么要限制密码的长度?

我应该对密码施加最大长度吗?

所有人都反对这一点。提到事情,比如

  • 节省存储空间
  • 旧的 Unix 系统经验
  • 与不支持长密码的遗留系统交互
  • 约定(即“我们一直这样做”)
  • 简单的天真或无知。
  • 明文存储
  • 另外,a maximum length specified on a password field should be read as a SECURITY WARNING通过这个答案 - https://stackoverflow.com/a/99724/932473
  • ETC

所以,我认为我不符合其中一种情况。当然,我同意愚蠢的限制,比如最大长度为 10,甚至更糟糕的是 8 或 6,但 30、40 或更多长度的密码(盐渍)不被认为是安全的吗?从这篇文章(虽然有点旧),但它说

it can make only 71,000 guesses against Bcrypt per second

http://arstechnica.com/security/2012/12/25-gpu-cluster-cracks-every-standard-windows-password-in-6-hours/

这适用于 8 个字符的密码。所以,我想象自定义彩虹表将有多么巨大,可以暴力破解一个 30 或更多字符的密码(考虑到每个密码都有自己的盐),因为彩虹表的大小呈指数增长

引用同一篇文章的评论

每次在密码中添加一个字符时,通过暴力破解的难度都会成倍增加。例如,8 个字符的密码具有 95^8 个组合的键空间,而 20 个字符的密码具有 95^20 个组合的键空间。

因此,对于一个带有 bcrypt 的 20 长度密码,需要 95^20 / (71 000 * 3600 * 24 * 365) ~ 10 的 28 度年(如果我做得对的话)

qsn1:现在,在这种情况下,对于河豚来说,有一个含义是不将密码最大长度限制为 72,因为在任何情况下,所有内容都将被截断,因此这里没有额外的安全增益。

qsn2:即使存在盐(对于每个用户来说都是唯一的并且保存在数据库中),毕竟我想在密码中添加胡椒(在应用程序中硬编码而不是保存在数据库中)。我知道是否会增加一点额外的安全性,但我认为以防万一 db(或 db 备份)只是泄漏,胡椒会很有用。 https://security.stackexchange.com/a/3289/38200 因此,为了能够添加 20 个字符的胡椒,我需要将密码的最大长度设置为 50 左右。我认为是这样的:假设用户使用 70 个字符,在大多数情况下(如果不是全部),它会是一些类似的短语或smth,而不是生成强大的短语,所以将用户限制为最大长度 50 并添加另一个 20-22 个字符的胡椒不是更安全,这绝对是更安全/随机的。另外,假设黑客正在使用“常用短语”的彩虹表,我认为72 character common phrase被黑客攻击的机会比50 character common phrase + 22 character random string. 那么,这种使用胡椒和 50 最大长度的方法是否更好,或者我做错了,最好保留 72 最大限制(如果 qsn1 没问题)?

谢谢

顺便提一句:

根据 Owasp,密码的合理最大长度为 160 https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet#Do_not_limit_the_character_set_and_set_long_max_lengths_for_credentials

谷歌的密码最大长度为 100

在此处输入图像描述

Wordpress 的最大限制为 50

https://signup.wordpress.com/signup/

4

2 回答 2

7

问题 1:没有理由限制密码长度,BCrypt 可以使用更长的密码,尽管只使用 72 个字符。你根本没有任何优势,但理论上你会阻碍密码管理器使用更长密码的人。如果您将来切换到另一种算法,则限制可能会有所不同,因此没有理由限制为 72 个字符。

问题 2:您最好使用另一种方法,而不是使用其他方法:使用服务器端密钥加密密码哈希。添加辣椒的原因是,攻击者必须在服务器上获得特权,因为没有密钥他无法开始暴力破解哈希(SQL 注入或丢弃的数据库备份不会这样做)。加密(双向)散列具有相同的优势。

  1. 这样您就不需要为辣椒保留字符,您可以使用密码中的所有 72 个字符。
  2. 与胡椒相比,服务器端密钥可以在必要时交换。辣椒实际上成为密码的一部分,并且在下次登录之前无法更改。
  3. 另一个讨论的观点是,理论上辣椒可能会干扰哈希算法。
于 2014-07-15T07:13:02.240 回答
-3

除了用户提供的密码的简单散列之外,还有其他用例希望使用 bcrypt 安全地散列整个任意长的字符串。人们可能还希望在将密码传递给 bcrypt 之前对密码进行加盐,以获得更高级别的熵。

我用来绕过字符限制的一种算法是使用中间哈希。因此,我没有直接对密码进行散列,而是使用较弱的散列机制,在 bcrypt 的长度限制内生成较短的字符串,然后使用 bcrypt 散列该中间字符串。中间散列不必像 bcrypt 那样是强散列,但如果您使用高度随机化的长盐,您将最大限度地提高这种方法的有效性。我当前的中间哈希是 sha512。

我用于散列密码的步骤如下:

  1. 使用 /dev/urandom 等源生成一个长的、加密安全的盐。(按用户执行此操作。如果您愿意,也可以附加应用程序范围的盐。)如果您计划将来进行密码验证,则需要存储此盐。
  2. 将盐连接到用户提供的密码。
  3. 将连接的值提供给 sha512 并捕获结果,这将是一个 128 字符的字符串,表示一个十六进制数。
  4. 要添加熵并利用整个中间盐,循环遍历整个 sha512 散列,获取一对十六进制数字,将这对的值转换为一个 ascii 字符,并使用每个字符构建一个压缩的中间散列,其中有 64 个字符长256 个可能的字符。
  5. 使用您的首选参数(例如成本)将最终压缩的中间哈希输入 bcrypt 并捕获生成的哈希。
  6. 您现在拥有一个安全哈希,它利用了您的长密码的全部值。
于 2018-01-19T20:23:31.883 回答