给密码加盐:最佳做法?


162

我一直很好奇...给哈希密码加盐时,哪种更好:前缀还是后缀?为什么?还是重要,只要你加盐?

解释一下:到现在,我们所有人(希望如此)都知道在对密码进行哈希处理以存储到数据库之前,应该先对密码加盐 [ 编辑:这样就可以避免Jeff Atwood最近发生的事情 ]。通常,这是通过在盐经过哈希算法之前将盐与密码连接起来来完成的。但是示例各不相同...一些示例在密码前加盐。一些示例在密码添加盐。我什至看到一些尝试将盐撒在中间的方法。

那么哪种方法更好,为什么呢?有没有一种方法可以减少哈希冲突的机会?我的Google搜索功能尚未对此问题进行过体面的分析。

编辑:乡亲们很好的答案!对不起,我只能选择一个答案。:)



1
@Jaccco:很棒的输入。谢谢!
伦道夫

3
最佳实践是使用加密功能,通过PBKDF2(标准),bcrypt甚至scrypt来为您加盐。感谢斯蒂芬指出这一点。
Maarten Bodewes 2012年

1
几乎所有标准密码哈希构造都需要结合使用salt和密码,因此您不必为此担心。如果您不使用标准密码哈希,请迁移到一个。
CodesInChaos

1
@Omu不好的建议。1)SHA-1的单个迭代速度太快,您至少应使用10000,即使那样也很弱。2)默认盐太小。最少8个字节,建议16个字节。
CodesInChaos

Answers:


111

前缀或后缀无关紧要,只不过是在密码中添加了一些熵和长度。

您应该考虑以下三件事:

  1. 您存储的每个密码的盐都必须不同。(这是一个普遍的误解。)
  2. 使用加密安全的随机数生成器。
  3. 选择足够长的盐。考虑一下生日问题。

Dave Sherohman很好地回答了另一个问题,为什么您应该使用随机生成的盐代替用户名(或其他个人数据)。如果您遵循这些建议,那么放盐的位置并不重要。


4
我添加了一个旧问题的链接,请阅读这些答案。基本上,通过不对每个密码使用不同的随机盐来承担不必要的安全风险,这在将来可能是一个真正的问题。
格奥尔格·舍利(GeorgSchölly)

39
站点范围内的随机盐是有害的,因为攻击者可以预先计算彩虹表并获取整个用户数据库。如果您不了解此信息,请不要编写登录/安全系统:)-您需要按用户使用盐。
09年

3
是的,每位使用者加盐。理想情况下,存储每个用户的迭代次数(这样您就可以随着时间的推移增加迭代次数)。任何体面的框架都将内置此功能。(.NET具有PasswordDeriveBytes,它将为您处理所有事情。)
MichaelGG,2009年

2
如果您正在设计任何类型的安全系统,那将是不使用每用户使用盐的想法。您的网站可能不是很有趣,但是考虑到用户在多个网站上使用相同的密码...试图确保数据库安全往往会失败:)
snemarch

2
当然,盐可以防止字典攻击,确切地说是通过使其变慢来防止。在密码中使用盐远远早于彩虹表。通过防止攻击者一次对哈希进行哈希处理然后将其与所有用户进行比较,专门添加了盐来减慢字典攻击速度。
格伦·梅纳德

27

我认为这都是语义。除了针对非常具体的威胁模型之外,将其置于之前或之后都没有关系。

它在那里的事实应该击败彩虹桌。

我提到的威胁模型是这样的情况,即对手可以在密码后附加/添加常见盐的彩虹表。(说NSA)您正在猜测他们是在前面添加还是在前面,但都没有。真是愚蠢,这是一个很糟糕的猜测。

最好假设它们具有存储这些彩虹表的能力,但是,例如,在密码中间散布着奇怪的盐的表则不能。在那种狭窄的情况下,我猜想散布是最好的。

就像我说的。这是语义。为每个密码选择一个不同的字符,一个较长的字符,并在其中包含奇数字符,例如符号和ASCII代码:©¤¡


@onebyone,该死!他发现了我的“密码盐”盐!
塞缪尔

6
@Samuel:我不了解你们,但是我们用'12345'作为盐。:)
Randolpho

@onebyone有效。我真正的意思是“普通的”,因为“在字符集Y中长度X之下的所有盐”在X,Y处是合理的。例如20个字符和字母数字大写/小写。可扩展的说下长度Z(说160)所有十六进制字符串,因为我认为哈希散列的彩虹表会..是有用的
汤姆·里特

1
@Randolpho:嘿,那也是我的盐!几率是多少?
阿德里安

并且确保盐是不可预测的/随机的:stackoverflow.com/questions/1645161/…–
Jacco

18

似乎没有人提及的真正答案是,两者都是错误的。如果您要实现自己的加密,那么无论您认为自己做的多么微不足道,都将犯错误。

HMAC是一种更好的方法,但是即使使用了SHA-1之类的东西,由于它的速度设计,您已经选择了不适合密码哈希的算法。使用bcrypt或可能的scrypt之类的东西,完全可以解决问题。

哦,甚至不要考虑将所产生的哈希值与编程语言或数据库字符串比较实用程序进行相等性比较。它们会逐个字符地进行比较,并且短路就false好像一个字符有所不同。因此,现在攻击者可以使用统计方法来尝试计算出什么是哈希,一次是一个字符。


1
关于最后一段:攻击者如何获得有关比较失败的确切字符数的任何信息?这没有任何意义..
Halloweenlv

1
你是正确的也是错误的。定时攻击是真实的,并且已经被反复证明是可行的,即使在可变延迟网络连接上也能以惊人的准确性来确定比较失败的确切位置。就是说,定时攻击实际上并不适用于常见的密码散列,因为找到只改变输出的一小部分的输入在计算上是不可行的。
史蒂芬·图瑟

9

它应该没有任何区别。无论您将盐放在何处,都将不再容易猜测哈希值。由于有意地是非线性的,所以哈希冲突既罕见又不可预测。如果它改变了安全性,那将暗示哈希问题,而不是盐分问题。


1
哈希冲突取决于哈希的大小。由于生日问题,很可能发生碰撞。
GeorgSchölly09年

2
仅当您截断结果时。无论如何,我仍然坚持认为盐的位置不会有任何区别,因为哈希的目的是使输入和输出之间的关系不包含任何模式。
Phil H

7

如果使用加密安全的哈希,则前缀或后缀无关紧要;散列的一点是,源数据中的任何一位更改(无论在何处)都将产生不同的散列。

什么重要的,虽然是使用长盐,用正确的密码PRNG生成它们,并且每用户的盐。在数据库中存储每个用户的盐不是安全问题,使用站点范围内的哈希


2
错误的答案:攻击者可以为许多经常使用的密码预先计算MD(pass),然后非常便宜地计算MD(pass + salt),因为消息摘要以增量方式工作以支持流传输。
Erwan Legrand 2013年

5

首先,术语“彩虹表”一直被滥用。A“彩虹”表只是一个特定类型的查找表,一个允许特定种类上的按键数据压缩的。通过用空间换取计算,将占用1000 TB的查找表压缩一千次,从而可以将其存储在较小的驱动器驱动器上。

您应该担心哈希密码查询表,彩虹或其他方式。

@ onebyone.livejournal.com:

攻击者具有“彩虹表”,该“彩虹表”不包含字典单词的哈希,而包含哈希计算的状态,就在哈希计算即将完成之前。

这样,用后缀salt暴力破解密码文件条目可能比使用前缀salt暴力破解便宜:依次为每个词典单词加载状态,将salt字节添加到哈希中,然后完成确定。使用带前缀的salt时,每个字典单词的计算之间不会有共同之处。

对于简单地通过输入字符串进行线性扫描的哈希函数(例如简单的线性同余生成器),这是一种实际的攻击。但是,经过密码学保护的哈希函数是经过精心设计的,具有多个回合,每个回合都使用输入字符串的所有位,因此,在添加盐之前先计算内部状态没有意义。例如,SHA-1有80发子弹。

此外,密码散列算法(如PBKDF)多次组合其散列函数(建议对PBKDF-2进行至少1000次迭代,每次迭代使用SHA-1两次),使这种攻击变得不切实际。


您应该仔细检查回合的描述。这些回合是基于每个块而不是整个消息。(否则,对流数据进行散列将要求一次又一次地回绕。)但是使用迭代确实可以防止问题被一再提及。
MichaelGG

4

BCrypt哈希(如果平台具有提供程序)。我喜欢您不担心会产生盐的问题,并且可以根据需要使它们更坚固。


3
就像我所知道的var一样,BCrypt Hash需要加盐,就像其他任何哈希方案一样。
雅科

2

在密码中插入任意数量的字符是最不期望的情况,因此也是社交上最“安全”的情况,但是在一般情况下,只要您使用的是每个密码唯一且很长的字符,这实际上并不十分重要。盐的字符串。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.