加盐的目标是抵抗预计算。
虽然您不能保证盐是全球唯一的,但您可以(正如您所说)生成足够大小的盐,以使其无法提前生成彩虹表(使它们“足够独特”)。
更一般地说,如果您询问如何创建盐,听起来您正在使用自己的散列方法,这可能具有教育意义,但通常不推荐。
相反,使用现有的哈希(例如 PBDKF2 或 bcrypt)(甚至更好,正如 CBHacking 在评论中正确建议的那样,scrypt 或 Argon2)。您不仅会自动继承他们现有的加盐方法(这已经足够了),而且您的实验将与密码存储最佳实践保持一致……这可能是更好的实践。
2018-04-03更新:Steve Thomas (sc00bz)在这里提出了一个很好的观点,即 Argon2 和 scrypt 在以通常被认为与大规模身份验证兼容的速度(<0.1 秒)使用时实际上对防御者来说更糟,而对于防御者来说更好速度与单个文件加密兼容的防御者(1 到 5 秒)。(这意味着从 0.1 秒到 1 秒的差距可能很有趣,并且需要针对您的特定环境进行测试)。换句话说,他的断言是,如果您尝试将 Argon2 或 scrypt 调整到 <0.1s 的速度,则结果对破解的抵抗力低于 bcrypt 在这些速度下的抵抗力。
在同一个线程中,Aaron Toponce 还提出了一个很好的建议,通过使用bcrypt(base64(sha-256(password)))
. (另请参见 Thomas Pornin 的类似答案)。需要 base64 的原因也很有趣——不要忽略它。
因此,如果您的用例是可扩展的、具有快速身份验证体验的防破解身份验证,bcrypt(base64(sha-256(password)))
这可能是一个好方法。(并且您需要将 bcrypt 的工作因子调整为适合您的身份验证速度窗口的最大值)。如果您的用户可以容忍等待一秒或更长时间进行身份验证,Argon2i 或 scrypt 可能会更好。请注意,随着硬件功能的提高,相对性能会随着时间的推移而发生变化——因此每 X 个月增加一次新哈希的 bcrypt 工作因子(如 Dropbox 所做的那样)将允许该方法随着时间的推移适应未来的功能。
更新 2019-09-01事实证明,将较快的哈希包装在较慢的哈希中而不先对较快的哈希进行加盐/加盐是危险的,因为可以针对来自另一个来源(例如另一个泄漏)的快速未破解的未加盐哈希进行批量测试包装散列,而不必先破解那些更快的散列。然后可以在单独的作业中以更高的速率攻击更快的哈希值。所以我上面的建议应该更新为 bcrypt(base64(sha256(password.salt)))
.