密码盐:前置与附加
我刚刚查看了 Django 中密码哈希的实现,注意到 它会在前面加上盐,因此哈希值的创建方式类似于 sha1(salt + 密码)
。
在我看来,盐有两个用途
防止彩虹表查找
好吧,前置/附加盐对于彩虹表来说并没有真正的区别。
针对暴力/字典攻击进行强化
这就是我的问题。如果有人想攻击被盗密码数据库中的单个密码,他需要尝试很多密码(例如字典单词或 [A-Za- z0-9] 排列)。
假设我的密码是“abcdef”,盐是“salt”,攻击者尝试所有 [az]{6} 密码。
使用前置盐,必须计算
hash("salt")
,存储哈希算法的状态,然后从该点继续进行每个排列。也就是说,完成所有排列将需要 26^6 次复制哈希算法的状态结构操作和 26^6hash([az]{6})
操作。由于复制哈希算法的状态非常快,因此盐几乎不会增加任何复杂性,无论它有多长。但是,如果附加了盐,攻击者必须为每个排列计算
哈希([az]{6} + salt 的排列)
,从而导致 26^10 次哈希运算。显然,附加盐会根据盐长度增加复杂性。
我不认为这是出于历史原因,因为 Django 相当新。那么前置盐有什么意义呢?
I just looked at the implementation of password hashing in Django and noticed that it prepends the salt, so the hash is created like sha1(salt + password)
, for example.
In my opinion, salts are good for two purposes
Preventing rainbow table lookups
Alright, prepending/appending the salt doesn't really make a difference for rainbow tables.
Hardening against brute-force/dictionary attacks
This is what my question is about. If someone wants to attack a single password from a stolen password database, he needs to try a lot of passwords (e.g. dictionary words or [A-Za-z0-9] permutations).
Let's assume my password is "abcdef", the salt is "salt" and the attacker tries all [a-z]{6} passwords.
With a prepended salt, one must calculate
hash("salt")
, store the hash algorithm's state and then go on from that point for each permutation. That is, going through all permutations would take 26^6 copy-hash-algorithm's-state-struct operations and 26^6hash(permutation of [a-z]{6})
operations. As copying the hash algorithm's state is freakin fast, the salt hardly adds any complexity here, no matter how long it is.But, with an appended salt, the attacker must calculate
hash(permutation of [a-z]{6} + salt)
for each permutation, leading to 26^10 hash operations. So obviously, appending salts adds complexity depending on the salt length.
I don't believe this is for historical reasons because Django is rather new. So what's the sense in prepending salts?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
两者都不做,请使用标准的密钥派生函数,例如PBKDF2。永远不要推出自己的加密货币。这太容易出错了。 PBKDF2 使用多次迭代来防止暴力破解,这比简单排序有更大的改进。
在处理盐后预先计算哈希函数的内部状态的技巧可能并不容易实现,除非盐的长度对应于底层块密码的块长度。
Do neither, use a standard Key derivation function like PBKDF2. Never roll your own crypto. It's much too easy to get it wrong. PBKDF2 uses many iterations to protect against bruteforce which is a much bigger improvement than the simple ordering.
And your trick pre-calculating the internal state of the hash-function after processing the salt probably isn't that easy to pull off unless the length of the salt corresponds to the block-length of the underlying block-cypher.
如果在前面添加了盐,攻击者可以为盐创建哈希状态数据库(假设盐足够长以进行哈希步骤),然后运行字典攻击。
但如果附加了盐,攻击者可以为密码字典创建这样的数据库,并另外仅计算盐的哈希值。鉴于盐通常比密码短(例如 4 个字符的盐和 8 个字符的密码),攻击速度会更快。
If salt is prepended, attacker can make hash state database for salts (assuming salt is long enough to make a hashing step) and then run dictionary attack.
But if salt is appended, attacker can make such database for password dictionary and additionally compute only salt's hash. Given that salt is usually shorter than password (like 4 chars salt and 8 char password), it will be faster attack.