由于有关盐渍散列的问题经常出现,而且似乎对这个问题有些混淆,所以我扩展了这个答案。
什么是盐?
盐是一种随机一组固定长度的字节,添加到哈希算法的输入中。
为什么盐渍(或种子)是有用的哈希?
向散列中添加随机盐确保相同的密码将产生许多不同的散列。SALT通常与散列函数的结果一起存储在数据库中。腌制散列有以下几个原因:
- 盐渍大大增加了预计算攻击的难度/成本(包括
彩虹桌)
- 盐析确保相同的密码不会导致相同的散列。这将确保您无法确定两个用户是否具有相同的密码。和,
更重要的是
,您无法确定同一人是否在不同的系统中使用相同的密码。 盐析增加了密码的复杂性,从而大大降低了两者的有效性。字典-和生日袭击.
(只有当盐是
与散列分开存储)。- 适当盐渍
大
增加预计算攻击的存储需求,直到它们不再实用的地步。(8个字符区分大小写的alpha-数值密码,16位SALT,散列为128位值,将占用不到200 艾比
没有彩虹减少)。
盐没必要保密。
SALT不是一个秘密密钥,而是通过使散列函数特定于每个实例来“工作”。在盐渍散列中,没有一散列函数,但每个可能的盐值都有一个。这可以防止攻击者攻击。N散列密码小于N乘以攻击一个密码的成本。这就是盐的要点。
“秘密盐”不是盐,它被称为“密钥”,这意味着您不再计算散列,而是计算消息认证码(麦克)计算MAC是一项棘手的工作(比简单地将一个键和一个值相加到一个散列函数中要复杂得多),这是一个完全不同的主题。
盐一定是随机的对于使用它的每一个实例。这确保了攻击者必须单独攻击每个盐度散列。
如果您依赖于您的盐分(或盐渍算法)是秘密的,您将进入默默无闻(不起作用)。最有可能的是,你不会从盐保密中获得额外的安全性;你只会得到一种温暖而模糊的安全感。因此,它没有使你的系统更加安全,它只是分散了你对现实的注意力。
那么,为什么盐必须是随机的呢?
从技术上讲,盐应该是独树一帜..对于每个散列密码,SALT的意义是不同的。这意味着世界各地..由于没有按需分配唯一盐的中央组织,我们必须依靠第二个最好的方法,即用不可预测的随机发生器进行随机选择,最好是在一个足够大的盐空间内进行随机选择,使碰撞不可能发生(两个例子使用相同的盐值)。
尝试从某些“可能是唯一的”数据(如用户ID)中提取盐分是很有诱惑力的,但由于一些令人讨厌的细节,此类方案常常失败:
如果你用例如,用户ID,一些坏人,攻击不同的系统,可能只是汇集他们的资源,并为用户ID 1到50创建预先计算的表。用户ID是唯一的。全系统但不是世界各地.
同样适用于用户名每个Unix系统有一个“根”,但世界上有许多根。一个彩虹表的“根”将是值得的努力,因为它可以应用到数百万系统。更糟糕的是,还有许多“bob”存在,许多人没有系统管理员培训:他们的密码可能很弱。
唯一性也是暂时的。有时,用户会更改他们的密码。每人新密码..新盐必须被选中。否则,攻击者获取旧密码的哈希和新密码的哈希可能会同时攻击两者。
使用从密码安全的随机盐,不可预测的PRNG可能是某种过火,但至少它证明保护你免受所有这些危险。这并不是要阻止攻击者知道个人盐就是,它不给他们巨大的,肥胖的目标,将用于大量的潜在目标。随机选择使得目标尽可能薄,这是可行的。
最后:
使用随机,均匀分布,高熵盐。每当您创建新密码或更改密码时,请使用新的SALT。将盐与散列密码一起存储。喜欢大盐(至少10字节,最好是16字节或更多)。
SALT不会将坏密码转换为好密码。它只会确保攻击者至少要付出字典攻击的代价。各他破解了坏密码。
有用的资料来源:
stackoverflow网站:密码散列的非随机盐
布鲁斯·施耐尔:实用密码学(书)
Matasano安全:够了彩虹桌
usenix.org:Unix地窖自1976年起使用盐
owasp.org: 为什么加盐
openWall.com: 盐类
免责声明:
我不是保安专家。(虽然这个答案是由托马斯·波宁)
如果有任何安全专家发现有什么问题,请做评论或编辑这个wiki的答案。