hash(hash())vs salted hash

You*_*usf 3 security hash salt password-hash

由于Rainbow表的引入,并且仅使用散列密码(例如:MD5)来存储数据库中的密码并不是最好的安全方式.

当人们谈论盐渍哈希时,总是以这种方式使用它hash(password . salt)甚至是hash(hash(password) . salt).

我不知道为什么要使用salt,并为每个密码添加额外的条目来存储盐?为什么我们不使用hash(hash(password)),甚至hash(hash(hash(password)))

放盐更安全吗?还是只是感觉更复杂?

TTo*_*oni 23

您可以在哈希(pwd)的两倍时间内构建基于哈希字典(哈希(pwd))的彩虹表(甚至更少,因为性能主要是关于光盘写入),它甚至不会更大.使用盐极大地扩大了表格所需的大小,使其变得不切实际.

另外(更重要的是),用户通常拥有相同的密码.如果您没有为每个用户设置单独的盐,如果您已经破坏了一个用户密码,那么您已经破坏了所有其他具有相同密码的用户.

  • Hrm ..第二段从来没有发生在我身上.对于每用户盐,这是一个很好的论据. (2认同)

Jon*_*eet 12

为了简单起见,我们假设每个人都使用数字作为密码.

如果每个人都使用8位数作为他们的密码,那就是100,000,000种可能性.如果您试图破坏系统,则需要散列所有这些可能性.如果你有一个"散列哈希哈希",你仍然需要散列那些100,000,000种可能性 - 只是稍微复杂一点.

现在让我们假装我们有一个4位数的盐.现在,而不是100,000,000个可能性,有1,000,000,000,000 ......我们给潜在的攻击者提供了10,000倍的工作量,而不是仅仅3倍的工作量.

基本上,将盐视为人为地使每个人的密码更长的一种方式,从而扩展字典攻击必须处理的空间.

编辑:为了清楚,鉴于盐也是以纯文本形式提供的,您仍然只有100,000,000种可能性来尝试攻击任何一个哈希值.但是,这意味着在尝试使用一个密码的可能性之后,攻击者将没有任何有用的信息来攻击另一个密码.如果没有盐,攻击者可以创建一个100,000,000种可能性的字典,然后只知道它们的哈希值,就可以知道数据库中的所有密码.换句话说,盐有助于防止大量攻击.它们还意味着你无法预生成字典:为了有效地攻击单个密码,你必须事先知道盐.如果没有salt,您可以在访问哈希值之前计算每个可能密码的哈希值.

  • 我没有投票,但我认为你的解释有点误导.因为盐是已知的,所以它不会更难以猜测个人密码.它只是建立一个表来攻击多个密码更难,并且只有每个用户都有一个不可预测的盐. (2认同)

Cam*_*ner 6

如果您不使用salt,则攻击者可以构建单个彩虹表,可用于攻击数据库中的每个密码.多次哈希并不会在没有盐的情况下保护你,因为彩虹表通过将哈希链接在一起完全按照你描述的方式工作:hash(hash(password)).

如果为每个用户添加随机盐,则攻击者无法重复使用同一个表来破解两个密码,因此他们的工作变得更加困难.作为额外的好处,如果使用salt,具有相同密码的两个用户将散列到不同的值.

你迭代哈希的想法仍然很好,但你也需要盐.如果你这样做:

function hashPassword(password, salt) {
    result = hash(salt . password)
    for (i = 0; i < 1000; i++) {
        result = hash(salt . result)
    }
    return result
}
Run Code Online (Sandbox Code Playgroud)

然后你使攻击者的工作难度增加1000倍,对合法用户的影响可以忽略不计.请注意,攻击者可以在单个低端计算机上每秒测试数百万个候选密码 - 哈希函数设计得很快.这1000次迭代循环可以将可行的攻击改为需要100年或更长时间的攻击.当计算机在18个月内加速时,只需将迭代次数更改为2000.

salt,散列算法和迭代计数不需要保密,可以与计算的散列一起存储在数据库中.您可以选择固定的迭代计数和哈希算法,但必须为每个用户随机生成盐.