bcrypt,河豚的密码最大长度
Posted
技术标签:
【中文标题】bcrypt,河豚的密码最大长度【英文标题】:Password max length with bcrypt, blowfish 【发布时间】:2014-09-05 05:45:31 【问题描述】:我的问题源于此 How to hash long passwords (>72 characters) with blowfish
我正在使用 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
Why restrict the length of a password?
Should I impose a maximum length on passwords?
所有人都反对这一点。提到一些事情,比如
节省存储空间 旧 Unix 系统经验 与不支持长密码的旧系统交互 约定(即“我们一直这样做”) 单纯的天真或无知。 明文存储 另外,a maximum length specified on a password field should be read as a SECURITY WARNING
,通过这个答案 - https://***.com/a/99724/932473
等
所以,我认为我不符合其中一种情况。当然,我同意愚蠢的限制,比如最大长度为 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 或更多字符的密码(考虑到每个密码都有自己的盐),因为彩虹表的大小呈指数增长
引用同一篇文章的cmets
每次您在密码中添加一个字符,您的密码都会成倍增加 增加通过蛮力破解所需的难度。为了 例如,一个 8 字符的密码具有 95^8 个组合的键空间,而 一个 20 字符的密码具有 95^20 个组合的键空间。
因此,对于一个 20 长度的密码和 bcrypt 是必要的 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
google 的密码最大长度为 100
Wordpress 的最大限制为 50
https://signup.wordpress.com/signup/
【问题讨论】:
我不确定除了所有这些文本之外的实际问题是什么,但如果底层算法最多使用 X 个字符,您也应该将输入限制为 X 个字符,以明确表明更多字符只是将不被使用,因此不会增加安全性。此外,security SO:Do any security experts recommend bcrypt for password storage? 和与之相关的问题可能会引起您的普遍兴趣。 @OlegEstekhin,问题是关于方法,如果它在安全方面是正确的/可以的。第二个qsn是关于使用胡椒的。感谢您的链接。 【参考方案1】:除了用户提供的密码的简单散列之外,还有其他用例希望使用 bcrypt 安全地散列整个任意长的字符串。人们可能还希望在将密码传递给 bcrypt 之前对密码进行加盐,以获得更高级别的熵。
我用来绕过字符限制的一种算法是使用中间哈希。因此,我没有直接对密码进行散列,而是使用较弱的散列机制,在 bcrypt 的长度限制内生成较短的字符串,然后使用 bcrypt 散列该中间字符串。中间散列不必像 bcrypt 那样是强散列,但如果您使用高度随机化的长盐,您将最大限度地提高这种方法的有效性。我当前的中间哈希是 sha512。
我使用哈希密码的步骤如下:
-
使用 /dev/urandom 等源生成一个长的、加密安全的盐。 (按用户执行此操作。如果您愿意,也可以附加应用程序范围的盐。)如果您计划将来进行密码验证,则需要存储此盐。
将盐连接到用户提供的密码。
将连接的值提供给 sha512 并捕获结果,该结果将是一个 128 字符的字符串,表示一个十六进制数字。
要添加熵并利用整个中间盐,循环遍历整个 sha512 散列,获取十六进制数字对,将这对的值转换为 ascii 字符,并使用每个字符构建一个压缩的中间散列,长度为 64 个字符其中有 256 个可能的字符。
使用您的首选参数(例如成本)将最终压缩的中间哈希输入 bcrypt 并捕获生成的哈希。
您现在拥有一个安全哈希,该哈希利用了您的长密码的全部值。
【讨论】:
Homebrew KDF 模式总是不鼓励使用。使用类似 HKDF 的方法将熵扩展/提取到自定义长度。【参考方案2】:问题 1: 根本没有理由限制密码长度,BCrypt 可以使用更长的密码,尽管只使用 72 个字符。你根本没有任何优势,但理论上你会阻碍密码管理器使用更长密码的人。如果你以后改用另一种算法,限制可能会有所不同,所以没有理由限制为 72 个字符。
问题 2: 您最好使用另一种方法,而不是使用其他方法:使用服务器端密钥加密密码哈希。添加辣椒的原因是,攻击者必须在服务器上获得特权,因为没有密钥他无法开始暴力破解哈希(SQL 注入或丢弃的数据库备份不会这样做)。加密(双向)散列具有相同的优势。
-
这样您就不需要为辣椒保留字符,您可以使用密码中的所有 72 个字符。
与胡椒相比,服务器端密钥可以在必要时交换。胡椒实际上成为密码的一部分,并且在下次登录之前无法更改。
discussed 的另一点是,理论上辣椒可能会干扰哈希算法。
【讨论】:
强制执行 72 字节限制至少有一个原因。尽管这可能是不太可能的情况。如果您正在验证密码的强度,前 72 个字节可能不是很安全,而未截断的版本可能被认为非常安全。因此,在进行验证时,您的支票会说密码是安全的,但在加密时却不是。例如,假设限制为 8 个字节,而不是 72 个字节。passwordvqYMzPJ3jc
是未截断的强密码,但一旦加密,它基本上是最容易猜到的密码。
@Cully - 这确实是极不可能的,如果用户关心 72+ 字符密码(s)他也关心安全性并且不会使用弱前导 63 字符部分。 72+ 字符密码很难输入,它们是从密码管理器中复制的,并且此类工具不会创建弱密码。最后,没有任何理智的黑客会开始暴力破解 63+ 字符部分的弱前导部分,更难的是创建这样长度的弱部分,必须写类似aaaa...
的东西。但理论上你是对的。以上是关于bcrypt,河豚的密码最大长度的主要内容,如果未能解决你的问题,请参考以下文章
我应该使用啥列类型/长度将 Bcrypt 散列密码存储在数据库中?
SHA512 与 Blowfish 和 Bcrypt [关闭]