在单向哈希之前放置盐

信息安全 密码学 哈希
2021-08-19 05:51:37

在单向散列中,通常将盐添加或附加到秘密,然后对其进行散列:(盐+秘密)或(秘密+盐)。我把这个比喻想象成盐落在一盘食物上。它当然不会全部落在盘子的开始或结束时。

相反,如果我像下面这样在秘密中随机分配盐,是否有任何安全优势?

每隔一个字母分发盐的简单示例:


Salt = lk2jn35  
Secret = hello  
Salted = lhke2ljlno35

我敢肯定,我还可以想出一个“掩码”变量来描述密钥中盐的分布,并且盐本身的分布可能会像这样随机化:


Salt = lk2jn35  
Secret = hello  
SaltMask = 010011101011  
Salted = hlelk2jlno35 

问题是,除了传统的前置或附加方法之外,这是否有任何额外的安全优势

2个回答

如果散列函数是“完美的”(即随机预言),那么盐和密码如何混合在一起并不重要。然而,完美的散列函数并不存在。我们甚至不知道是否存在“稍微不完美”的哈希函数(不是随机预言但仍保证抗原像的函数)。实用的散列函数具有与其内部结构相关的“怪癖”,必须通过注意输入的准备方式来避免。很难说将密码和盐结合起来哪种方式更好,因此通常的方法是将其留给训练有素的密码学家。这些人经过几十年的努力,提出了一些看起来 要强大,一个单独的开发人员不太可能通过将一两个功能组合在一起来提出更好的东西。

无论如何,即使您混合密码和盐的方法很好(可能很好,但很难确定),您的功能仍然太快了。您应该在这里有成千上万甚至数百万的嵌套哈希函数调用,因为密码哈希函数本来就应该很有关该问题的完整处理,请参见此答案

请参阅为什么我们推荐的总是 `HASH( salt + password )`?. 如果您正在寻找一种安全的密码验证方法,有更好的选择,正如 Thomas Pornin 在他对该问题的回答中指出的那样,Tom Leek 在上面指出。

H(salt|secret)方法可能容易受到长度扩展攻击,尽管我看不出它在这种情况下有用的方法(因为必须知道两个组件才能执行这种类型的攻击,所以没有任何好处),没有理由解雇它立即。

假设选择的哈希算法适合目的,那么我建议以下注意事项:

  • salt 的目的不是“改进”哈希,而是使执行某些预先计算的攻击变得昂贵
  • 盐级联是一种计算上微不足道的操作,并且在费用方面没有适当的键拉伸那么有效。将位改组几次是一项相当简单的操作。
  • 鉴于此处使用的盐的意图,您可以说的一件事是更长和更随机的盐更能达到其预期目的。因此,如果您只是简单地打乱输入的位,它不会使盐更(或更少)有效。

假设“更好的安全性”等同于“对攻击者来说更难”,没有任何好处,因为攻击者知道系统并且挑战并不比以前更复杂。秘密仍然是相同的秘密,恢复它所需的工作量几乎没有变化。

(而且,与以往一样,您有可能忽略了系统的某些微妙方面,或者今天只是运气不佳,并且您以某种方式设法使整体安全性变得更糟。)