BCrypt、Blowfish 密码最大长度是多少?

9
我的问题源自于这个链接:如何使用blowfish哈希长密码(>72个字符)
我正在使用bcrypt(blowfish)来哈希密码。因此,我从这个问题中发现它有一个72个字符的限制:https://security.stackexchange.com/questions/39849/does-bcrypt-have-a-maximum-password-length
因此,我开始考虑限制密码的最大长度,但在阅读了这些问题及其答案后,我决定不要这样做。

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

为什么要限制密码长度?

我是否应该对密码施加最大长度限制?

所有这些都是反对的。提到了一些事情,比如

  • 节省存储空间
  • 旧的Unix系统经验
  • 与不支持长密码的旧系统的交互
  • 惯例(即“我们一直这样做”)
  • 简单的幼稚或无知。
  • 以明文形式存储
  • 此外,在密码字段上指定的最大长度应被视为安全警告,来自这个答案 - https://dev59.com/1XVD5IYBdhLWcg3wE3Ro#99724
  • 等等

所以,我不认为我符合这些情况之一。当然,我同意像最大长度为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个字符长度的密码,根据该公式需要10的28次方年才能破解(如果我做对了的话)。

问题1:在这种情况下,对于blowfish,是否有意义不将密码最大长度限制为72,因为在任何情况下,超过该长度的所有内容都将被截断,因此在此处没有额外的安全性提升。

问题2: 即使盐存在(对于每个用户都是唯一的,并保存在数据库中),我仍然想将胡椒粉(硬编码在应用程序中而不是保存在数据库中)添加到密码中。我知道这会增加一点额外的安全性,但我认为如果仅泄漏了数据库(或数据库备份),胡椒粉也会有用,以防万一。 https://security.stackexchange.com/a/3289/38200 因此,为了能够添加比如20个字符的胡椒粉,我需要将密码最大长度设为约50个字符。我这样想:假设用户正在使用70个字符,在大多数情况下(如果不是全部情况),它将是一些短语之类的东西,而不是生成的强密码,因此限制用户最大长度为50并添加另外20-22个字符的胡椒粉肯定更安全/随机。此外,假设黑客正在使用“常见短语”的彩虹表,我认为被破解的72个字符的常见短语的机会更高,而不是50个字符的常见短语+22个字符的随机字符串。那么,使用胡椒粉和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

enter image description here

WordPress最大限制为50。

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


除了所有这些文本之外,我不确定实际问题是什么,但如果底层算法最多使用X个字符,则您应该将输入限制为X个字符,以明确表示更多的字符不会被使用,因此也不会增加安全性。此外,安全SO:有没有安全专家推荐bcrypt用于密码存储?和与之相关的问题可能对您有普遍的兴趣。 - Oleg Estekhin
@OlegEstekhin,这个问题是关于安全方面的正确/可行方法。第二个问题是关于使用pepper。感谢提供链接。 - dav
2个回答

7
问题1: 没有理由限制密码长度,BCrypt可以处理更长的密码,尽管只使用了72个字符。您根本没有任何优势,但从理论上讲,您会阻碍使用更长密码的密码管理器的人。如果您将来切换到另一个算法,则限制可能会不同,因此没有理由限制为72个字符。 问题2: 与其使用pepper,不如采用另一种方法:使用服务器端密钥加密密码哈希。添加pepper的原因是攻击者必须获得服务器特权,因为没有密钥,他无法开始暴力破解哈希值(SQL注入或数据库丢弃备份都不行)。使用加密(双向)哈希具有相同的优点。
  1. 这样您就不需要为pepper保留字符,可以使用密码的全部72个字符。
  2. 与pepper相比,服务器端密钥可以在必要时进行更换。pepper实际上成为密码的一部分,直到下次登录才能更改。
  3. 另一个讨论的观点是,pepper理论上可能会干扰哈希算法。

强制实行72字节限制至少有一个原因,尽管这是一个可能性很小的情况。如果您正在验证密码的强度,则前72个字节可能不太安全,而未截断版本可能被认为非常安全。因此,在进行验证时,您的检查将说密码是安全的,但在加密时,它并不安全。例如,假设限制不是72字节,而是8字节。passwordvqYMzPJ3jc未截断时很强壮,但一旦加密,它就是最容易猜测的密码。 - Cully
@Cully - 这确实极不可能,如果用户关心72个或更多字符的密码,他/她也会关心安全,并且不会使用弱的前63个字符部分。72个或更多字符的密码几乎不会被键入,它们是从密码管理器中复制的,而这种工具不会创建弱密码。最后,没有任何理智的黑客会从弱的前63个或更多字符部分开始暴力破解,更何况很难创建一个这么长的弱部分,必须写类似于aaaa...的东西。但从理论上讲,你是正确的。 - martinstoeckli

-2
除了简单地对用户提供的密码进行哈希外,使用bcrypt安全哈希任意长度字符串的整个内容还有其他用例。您可能还希望在将其传递到bcrypt之前为密码添加盐以获得更高级别的熵。
我用于绕过字符限制的算法之一是使用中间哈希。因此,我不直接对密码进行哈希,而是使用较弱的哈希机制,在bcrypt的长度限制范围内产生较短的字符串,然后使用bcrypt哈希该中间字符串。中间哈希不必像bcrypt那样强大,但如果您使用高度随机化且长时间的盐,则可以最大程度地提高此方法的有效性。我的当前中间哈希是sha512。
我用于哈希密码的步骤如下:
  1. 使用像/dev/urandom这样的源生成一个长的、加密安全的盐。(每个用户都要这样做。如果您喜欢,还可以附加一个应用程序范围的盐。) 如果您计划在将来进行密码验证,您需要存储此盐。
  2. 将盐连接到用户提供的密码上。
  3. 将连接后的值馈送到sha512中并捕获结果,这将是一个128个字符的字符串,表示十六进制数字。
  4. 为了增加熵并利用整个中间盐,循环遍历整个sha512哈希,取出一对十六进制数字,将该对的值转换为ascii字符,并使用每个字符构建一个紧凑的中间哈希,该哈希长度为64个字符,其中有256个可能的字符。
  5. 将最终压缩的中间哈希馈送到bcrypt中,使用您喜欢的参数(如成本)并捕获结果哈希。
  6. 现在,您拥有了一个安全的哈希,它利用了您的长密码的全部价值。

1
Homebrew KDF模式始终不被推荐。使用像HKDF这样经过验证的东西来将熵扩展/提取到自定义长度。 - Patrick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接