我花了一个小时阅读盐腌,但仍然不明白它是如何实现的。如果我错了,请原谅我,但我想要腌制的方式是,存储随机字符串的ArrayList,例如100个字符串。现在当用户注册时,方法从数组列表中获取一个随机字符串并检索数组中的字符串索引以插入到我的数据库中,然后将该随机字符串应用于用户输入的密码,然后散列整个字符串并存储到数据库中。
现在,当用户登录时,将检索随机字符串ArrayList的索引,然后将其应用于输入的密码,然后散列整个字符串并比较2个密码。
这是一种很好的腌制方式吗?这被归类为腌制吗?
答案 0 :(得分:1)
最好为每个用户/密码哈希使用唯一的盐,而不是重复使用有限的100种盐。
原因在于黑客一旦获得密码就会尝试破坏充满密码的数据库,特别是使用彩虹表来查找多个用户之间共享的已知值。
例如(伪代码):
这很糟糕,因为一旦黑客破解了第一个密码哈希,两个用户都会受到攻击。
//BAD WAY
var nonUniqueSalt = "some salt value";
var userPass1 = "P@ssword!";
var userPass2 = "P@ssword!";
//Bad! This will be true!
var isSame = (DoHash(userPass1 + nonUniqueSalt) == DoHash(userPass2 + nonUniqueSalt));
这种方式更好,因为即使密码相同,盐也不同,因此黑客无法使用彩虹表,并且不得不单独破坏每个用户的密码。
//BETTER WAY
var uniqueSalt1 = "unique salt 1";
var userPass1 = "P@ssword!";
var uniqueSalt2 = "unique salt 2";
var userPass2 = "P@ssword!";
//Better! This will be false.
var isSame = (DoHash(userPass1 + uniqueSalt1) == DoHash(userPass2 + uniqueSalt2));
至于腌制"算法"在评论中提到的一些用户,除了尝试使每个用户的盐独特之外(由于上述原因),你真的不必担心它。
在实践中,无论你使用什么样的盐都需要与密码哈希一起存储在数据库中,所以一旦黑客拥有了数据库,无论你怎么做,他都会拥有你用于盐的价值得出它。
因此,使用基于Guid.NewGuid()之类的盐.ToString()足以让每次登录都具有唯一值。