Password hashing, salt and storage of hashed values
假设您可以自由决定如何将哈希密码存储在DBMS中。像这样的计划有明显的弱点吗?
要创建存储在DBMS中的哈希值,请执行以下操作:
- 作为salt的一部分,dbms服务器实例唯一的值,
- 用户名作为salt的第二部分,
- 创建salt与实际密码的连接,
- 并使用sha-256算法散列整个字符串,
- 并将结果存储在DBMS中。
这意味着,任何想要产生冲突的人都必须分别为每个用户名和每个DBMS服务器实例进行工作。我计划保持实际散列机制的灵活性,以允许使用新的NIST标准散列算法(sha-3),该算法仍在研究中。
"DBMS服务器实例独有的值"不需要保密,尽管它不会随意泄露。其目的是确保如果有人在不同的DBMS服务器实例中使用相同的密码,则记录的哈希值将不同。同样,用户名也不是秘密的——只是正确的密码。
首先使用密码,其次使用用户名和"唯一值",或者对三个数据源进行任何其他排列,有什么好处吗?或者交错的字符串呢?
是否需要添加(并记录)随机salt值(每个密码)以及上面的信息?(优点:用户可以重复使用密码,但仍可能在数据库中记录不同的哈希值。缺点:必须记录盐。我怀疑优势远远大于劣势。)
有很多相关的问题-这个列表不太可能是全面的:
- 在数据库中加密/散列纯文本密码
- PHP密码的安全哈希和salt
- 把盐藏起来做土豆泥的必要性
- 客户端MD5哈希和时间盐
- 简单密码加密
- 制盐和开源软件
- 密码哈希:固定长度的二进制字段还是单字符串字段?
我认为这些问题的答案支持我的算法(尽管如果您只使用随机salt,那么"每服务器的唯一值"和用户名组件就不那么重要了)。
- 随机部分很重要,它可以防止预测攻击
- 您可以在文章列表中添加stackoverflow.com/questions/1645161/…。
- 另外,添加dba.stackexchange.com/questions/7492/…作为数据库管理员站点的一个很好的引导。
- 如果要更改用户名,将用户名添加到salt需要密码明文才能重置密码哈希。如果这是个问题。
- 从下面所有的评论中,我没有看到关于盐应该去哪里的答案(之前还是之后)?我想知道,如果盐位于之前、之后或可能同时位于两者之间,是否更难暴力地强制散列,或者可能它真的不重要放在哪里?
- @杰奇:我认为这没什么区别,但我会先放盐,这样它就有最大的机会影响根据下面的密码计算出的散列值。但是,它也应该在末尾随机化OK。也许更好的办法是先放点盐,再放点盐。和其他人不同。这意味着攻击者必须自定义您的salt散列密码,而不是能够使用对其他人的密码所做的工作。(参见LinkedIn攻击。)它平均增加了必须完成的工作量。即使如此,攻击者也可能走运。
- @blueshift我不是密码学家,但是……你不能通过要求提供密码来改变用户名来绕过这个问题吗?
- @黑光:是的。
盐只是需要随机的和独特的。它可以自由地称为它对攻击者没有帮助。许多系统将把纯文本salt存储在数据库中哈希密码旁边的列中。
salt有助于确保如果两个人(用户A和用户B)恰好共享同一个密码,则不明显。如果没有每个密码的随机和唯一salt,散列值将是相同的,显然,如果破解了用户A的密码,那么用户B必须具有相同的密码。
它还有助于防止哈希字典与已知密码匹配的攻击。例如彩虹桌。
此外,使用内置"工作因子"的算法也意味着,随着计算能力的增加,算法必须完成的创建散列的工作也会增加。例如,bcrypt。这意味着暴力攻击的经济性变得无法维持。可能创建已知哈希表会变得更加困难,因为创建这些哈希表需要更长的时间,"工作因子"的变化意味着需要创建更多的表。
- 盐渍还可以保护我们免受彩虹桌攻击
- 是的;正如我在对其他答案的评论中所指出的,我的问题在我写的时候发生了变形,我意识到随机盐是必要的,但没有花时间来反映它也是足够的。将用户名添加到组合中主要是延长哈希算法必须处理的数据,有助于保护短密码。我不确定额外的保护有多真实。
- 这个答案是错误的。salts的目的并不是"共享密码不明显"。其目的是使字典攻击更加困难。(允许像这样危险的错误响应标记为"答案"是该站点的致命设计缺陷。)
- "危险的错误"?它可能是不完整的(如果两个用户恰好共享同一个密码,它确实有助于保护),但是这个答案的危险在哪里?如果我知道的话,我会很乐意改正的。
- @我建议你阅读codahale.com/how-to-safety-store-a-password,找出你的答案为什么是危险的错误。长短不一是"蛮力比你想象的要快"。拥有SALT是必要的——没有它,人们只能使用预先计算好的查找表——但不足以用弱密码保护用户(大多数情况下是这样)。
- @格伦迈纳德:我同意你最后一部分的陈述。复选标记图标下面应该有一个可否决的图标,一旦答案被接受:a)为用户提供更新答案的时间,或b)强制将答案设置为"已否决"。
- @B你提供的链接是纯粹的(危险的)铺位。bcrypt在防止暴力攻击上并没有比加盐密码更有效。攻击者的目的是获得访问权。因此,他所需要做的就是残暴地输入可能的密码,而不是散列。bcrypt替代方案将计算费用转移到服务器上,因此是对资源的浪费,而不是更多。如果您使用的是密码12345,而我强行使用了该密码,不管您使用的加密技术在计算上多么昂贵,您都会被加密。随机盐很好,不允许弱密码!
- 格伦·梅纳德和开发人员克里斯提出了令人信服的论点。无论你如何伪装一个存储的密码,如果用户选择了一个弱的密码,暴力攻击将成功破解它。
- "无论你如何伪装一个存储的密码,如果用户选择了一个弱密码,暴力攻击将成功破解它。"那么,这是如何伪装密码的算法的错误呢?根据你的反应,我们很可能只是把我们的手扔到空中,然后说"去死吧!毫无意义,用户太笨了,无论如何他们都会被破解的。"
我觉得你把问题弄得太复杂了。
从问题开始:
您是否试图保护弱密码?
你想减轻彩虹攻击吗?
您建议的机制确实可以防止简单的彩虹攻击,因为即使用户A和用户B拥有相同的密码,哈希密码也会有所不同。确实如此,似乎是一个相当复杂的加盐密码方法。
- 当您将数据库迁移到另一个服务器时会发生什么?
- 可以更改每个数据库的唯一值吗?如果是,那么可以生成全局彩虹表;如果不是,则无法恢复数据库。
相反,我只需添加额外的列并存储适当的随机盐。这可以防止任何彩虹攻击。跨多个部署。
但是,它不会保护你免受蛮力攻击。所以,如果你试图保护那些密码糟糕的用户,你就需要找别的地方。例如,如果您的用户有4个字母的密码,即使使用salt和最新的哈希算法,也可能在几秒钟内破解。
- 很好的回答。10公里有投票和奖励!
- :p谢谢!
- 我认为你很可能是对的——在我写这个问题的时候,我意识到随机盐是必要的;我没有花时间注意到它也足够了。尽管如此,一个问题是给散列算法更多的数据来处理——用户名也有一点帮助,salt也是。恢复到另一个DBMS服务器实例是一个有效的问题——我没有想到这一点。用户名和salt就可以了,不需要100%的用户名。谢谢。
我认为你需要问自己,"你希望通过使这个过程变得更复杂而不仅仅是生成一个随机的盐值并存储它来获得什么?"你的算法越复杂,你越可能无意中引入一个弱点。不管我怎么说,这可能听起来很刺耳,但这是有帮助的——你的应用有什么特别之处,以至于它需要一个新的密码哈希算法?
- @彼得:没有冒犯-我明白你的意思。我写的"有什么不同"的一个方面是"确保具有相同密码的不同服务器存储不同的密钥"。正如其他评论中提到的,我在问题接近尾声时意识到随机盐是必要的;我没有发现它是足够的。散列中的额外数据有助于保护短密码和差密码。我无法评估的是这会产生多大的差异。
- 继续:如果salt是一个8字节的整数,而密码是一个字母,那么sha-256哈希是否真的足够保护它?如果用户名是3个字符,"服务器唯一"数据是一个32个字符的随机(但固定)字符串,这是否有助于保护数据—44字节的数据可以工作,而不仅仅是9字节。看起来应该更安全(9个字节可能被彩虹攻击;44个字节可能不那么容易被攻击)。也许"server unique"只需要是"固定的32字节字符串";…
- 继续(2):…或者它可能需要用固定字符串将"salt plus password"填充到64个字节(或者32个字节,或者其他一些数字)?或者这一切都是一场大惊小怪的追逐,真的没关系。
为什么不在密码中添加随机salt并散列该组合呢?接下来将哈希和salt连接到一个单字节[]并将其存储在数据库中?
随机salt的优点是用户可以自由更改其用户名。盐不一定是秘密的,因为它是用来防止字典攻击的。
- +1提到用户不再可以自由更改其用户名!
- @在这种情况下,我不希望用户更改他们的名字,谢谢。在某些情况下,这可能是有价值的,但就这个应用而言,用户的名字是固定的(或者更准确地说,如果有人改变了他们的名字,他们会变成一个新的,不同的用户)。仅仅使用随机的salt和密码可能是可以的;我有点担心,以确保有足够的材料让hash算法的牙齿进入-这是添加的原因的另一部分,而不仅仅是salt。在我写这个问题的时候,我意识到随机盐是必要的,我也没有注意到它是足够的。
- 用户仍然可以更改他们的用户名,但此时您必须重新刷新他们的密码。另一方面,使用随机盐与使用非随机盐有相同或更大的好处。