在应用 bcrypt 之前预哈希密码以避免限制密码长度

信息安全 密码学 密码 哈希 密码
2021-08-18 08:23:53

良好的做法是不要不必要地限制密码长度,以便可以使用适当长度的密码(对于 6/7 的骰子字来说可能是 35-45 个字符)。(请参阅例如我应该有一个最大密码长度吗?建议最大为 1K,以防止 DoS 而不会限制用户设置长密码的能力。)

bcrypt 也被普遍推荐(参见例如Do any security expert recommend bcrypt for password storage?http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you -需要知道-关于-s.html )

还建议使用盐(随机,并与密码哈希一起存储)——我相信通常建议使用 32 位(4 个字符)。(我理解 salt-size 的基本原理是“足够组合的数量比用户记录的数量大得多,并且足以使彩虹表变得不可行”——16 位对于第二部分来说就足够了,但可能不是第一次就够了。)

但 AIUI bcrypt 仅散列 55 个字节——盐分 4 个字符,密码留出 51 个字符。

我猜我们不应该只 bcrypt(left(password,51)) 而忽略最后一个字符。

我们是否应该将用户的密码限制在 50 个字符以内(对几乎每个人来说都足够了,但绝对不够)?

我们是否应该改用 bcrypt(sha256(salt+password)) 之类的东西,并允许最多 1K 个字符?还是添加 sha256(或 sha512?)步骤会以某种方式降低整体安全性?

scrypt 或 PBKDF2 是否有类似的长度限制?

(最后一个问题只是为了兴趣,真的——我意识到空间硬度/FPGA 阻力,scrypt 的相对新颖性,以及 bcrypt 与 PBKDF2 相比的 GPGPU 阻力是决定使用哪个散列时更重要的考虑因素。利用。)

2个回答

使用安全哈希函数对密码进行预处理是安全的;可以证明,如果 bcrypt(SHA-256(password)) 被破坏,那么要么密码被猜到,要么 SHA-256 的某些安全特性被证明是错误的。没有必要在那个水平上摆弄盐;只需对密码进行哈希处理,然后在结果上使用 bcrypt(使用盐,作为 bcrypt 的要求)。SHA-256 被认为是一种安全的散列函数。

盐的要点是唯一的——尽可能唯一,这样没有两个散列密码使用相同的盐值。32 位有点低;你应该使用更长的盐。如果你有n位盐,那么只要你有超过2 n/2 个散列密码,你就会遇到冲突(两个散列密码使用相同的盐)——在n = 32的情况下大约是 65000 ,一个不太高价值。你最好使用 64 位或更多的盐(使用 128 位就可以不用担心了)。

Bcrypt 使用 128 位盐和 55 个字符(最大)的密码。您不需要添加任何其他盐值;bcrypt 处理。

bcrypt 的设计者认为密码的 55 个字符限制不是问题,因为哈希具有 128 位输出。如果您的密码超过 55 个字符,则设计人员假定您已经提供了超过 128 位的熵,因此这不是问题。相反,NIST 指南将这仅视为 77 位熵。NIST 指南基于这样一个事实,即密码短语每个字符的熵低于随机密码,并且假设用户将密码短语用于更长的密码。为了更好地确保您获得完整的 128 位熵,您可以允许更长的密码并使用 SHA-256 或 SHA-384 对它们进行哈希处理,以将它们压缩到可接受的长度。您也可以通过使用没有长度限制的 scrypt 或 PBKDF2 来简化事情。除了计算耗时之外,Scrypt 还被设计为“内存难”;那将是我选择的算法。