在密码加密中使用随机盐?

4

我看到了一些关于这个主题的其他讨论,但似乎找不到一些关于在密码加密中使用随机盐的问题的答案。据我了解,步骤大致如下:

  1. 为用户生成一个随机盐。
  2. 将盐附加到他们的密码上。
  3. 使用类似SHA-2的方法对结果进行哈希处理。
  4. 将盐和哈希密码都存储在数据库中。

当检索用户密码并验证登录时,这种方法是如何工作的?有一个回复说应该检索用户的盐,将其附加到他们输入的密码上,然后进行哈希处理,最后与存储的哈希值进行比较,但这不会引起一些问题吗?具体来说:

  • 您如何检索盐而不危及该用户?如果有人想要暴力破解某个帐户的密码,他们是否能够检索从服务器返回以对输入的密码进行哈希处理的盐,从而消除添加盐所提供的安全性?
  • 如果我们通过在服务器端执行盐检索来避免前面的问题,那么我们不会在某个时候发送未加密的用户输入密码(以便稍后附加到检索到的盐上)吗?
6个回答

4
盐值绝不能在服务之外暴露出来 - 你的直觉是正确的,这样会暴露盐值并引入风险。
客户端和服务器之间的任何通信都应该通过SSL连接进行 - 或者至少使用某种交互加密方式。
请记住盐值的目的:使预计算哈希码变得更加困难,从而在数据库被攻击时防止密码被查找。8位盐可以使哈希空间扩大256倍,从而使预计算变得更加困难。盐值不是用于保护通信的 - 这方面有其他解决方案。

1
系统应该是安全的,即使盐算法被曝光。您提出的是“通过混淆来保证安全性”,但这从来不是安全的。所有好的加密算法即使在你知道它们的情况下也是安全的。 - ruslik
@ruslik 抱歉,我不明白你的意思。当然,算法应该被公开 - 这是良好安全性的公理。我所说的“盐”是指特定密码的实际盐值,而不是盐化算法。 - Bevan
1
@Bevan 抱歉,但是没有任何区别。 - ruslik
@ruslik 我的理解(始终可能被纠正)是盐作用在于提供额外的密钥位,和任何对称密钥一样,应保密。维基百科也同意(“为了最佳安全性,盐值应保密。” http://en.wikipedia.org/wiki/Salt_%28cryptography%29)。你认为我漏掉了什么? - Bevan
2
根据我的理解,如果算法被公开(假设可以在客户端生成),那么您无法保守秘密。 - ruslik
@ruslik 我觉得我明白你的意思了。如果你知道输入和算法,那么你可以生成输出,所以输出不能是秘密的。这是正确的 - 如果你知道盐和密码,你可以轻松生成盐哈希。但是,盐的目的是使反向操作更困难:如果你有盐哈希,如何获得密码?没有盐,对于给定的密码只有一个哈希,因此你可以预先计算它。用8位的盐,每个密码有256个盐哈希,需要更多的空间进行预计算。 - Bevan

2
您需要使用随机盐,因为使用它的目的是保护您免受某些攻击类型的攻击,例如字典攻击、暴力攻击和彩虹表攻击。因此,为每个密码生成随机盐并将哈希密码和盐存储在用户表中或附加到用户配置文件中非常重要。当您想要验证用户密码时,只需使用存储的盐对输入的密码进行哈希,并将其与存储的哈希值进行比较即可。我不相信@cherouvim的建议,因为他似乎不关心上述攻击。有关更多信息,我建议阅读Defuse Security的一篇令人惊叹、简单易懂的文章。
祝你好运。

  1. 为每个用户创建随机盐值
  2. 使用该盐值加密密码
  3. 将密码存储在数据库中
  4. 使用固定的公共盐值加密盐值,并将其保存在配置文件中
  5. 将加密后的盐值存储在数据库中。
- Suyash Jain

1

我使用一个固定的盐值(用于所有密码),它是硬编码在应用程序代码中的。假设盐值无法被暴露(例如通过应用程序的用户界面),这看起来足够简单且有效。


1
是的,你说得对。我认为最好在服务器端加盐,并在传输密码时为客户端使用https。 - cherouvim
1
但这意味着如果散列密码被攻击者窃取,他们可以并行攻击所有密码——这正是盐的作用所在。也就是说,如果每个用户都有一个独立的盐值,则每个哈希计算只能与该用户的哈希结果进行比较。但如果应用程序只有一个盐值,则每个哈希结果都可以与所有用户进行比较。而且,如果哈希值被泄露,两个不同的用户可以确定他们使用相同的密码。 - Damien_The_Unbeliever
@Damien_The_Unbeliever:你的意思是如果盐和哈希密码被攻击者获取。如果攻击者能够访问服务器(以便通过反向工程您的应用程序代码来查找盐),那么您还需要担心其他问题 :) - cherouvim
Damien在这里提到了一些非常重要的东西,那就是盐实际上是用来保护什么的——预像攻击(通过使计算变得不可行)。预像攻击发生在黑客可以预先生成哈希列表时,因此他拥有已知的密码/哈希组合列表。因此,当攻击者获得您的哈希时,他能够区分数据库中任何具有与其现有列表中任何哈希相同的哈希的用户的密码,而无需进行暴力破解。防止这种情况的方法是使用不同的唯一值为每个密码加盐。 - user1004499
此外,这与 OP 有关,因为如果数据库在应用程序中为每个用户使用相同的 salt,则攻击者只需破解单个 salt 就能生成整个哈希列表。此外,由于在那时我们假设黑客已经通过数据库访问了哈希值,所以说他可以获取到 salt。唯一的 salt 可行之处不在于难以获得它们,而是使用唯一的 salt 生成预定义的哈希列表会随着 salt 大小的增加而指数级变得更加困难(2^n)。 - user1004499
显示剩余2条评论

1

盐引入的安全性是,您可以获得比纯文本密码要大得多且非标准的哈希值。无论其算法是否关闭,它都可以保护数据库中以明文存储的哈希值免受彩虹表或字典攻击。

还建议递归地多次进行哈希,每个迭代可能都重新添加盐,以便暴力破解需要更长时间。

编辑:针对Bevan关于通信的说法:通常使用“一次性数字”(NONCE)方案在不安全的通道上传输密码。服务器向客户端提供一个以前从未使用过的随机字符串,客户端将其附加到纯文本密码上,计算哈希值,并发送。这可以保护您免受窃听攻击。


但是,如果盐值是固定的或者算法是封闭的,那么像字典攻击这样的方法是否可以通过将已知的盐值附加到每个尝试中来克服这个问题呢? - Jengerer
嗯,反编译算法并不是很困难,所以不要因为它是封闭的就感到安全。 - ruslik

1

不发送可用于登录的未加密值的唯一方法是使用SSL。如果哈希值被发送到服务器,则哈希本身可以被嗅探并用于登录。请在服务器端执行。

对于ruslik关于盐的说法,我表示赞同。它可以防止字典/彩虹攻击。对于平均密码+几个字节的随机二进制数据的彩虹表将非常庞大。


  • 它还不存在。常见哈希函数和常见单词和/或特定大小的单词的彩虹表已经存在。
- ruslik

0

哈希密码可以防止密码明文可见,加盐可以抵御字典攻击。至于在传输过程中保护密码,我建议使用SSL/TLS。


1
你在这个简单但完全正确的答案上做得很好。人们经常通过加盐来使事情变得复杂 - 它的唯一目的是保护免受字典(“预像”)攻击,没有其他作用。人们经常认为盐的增加长度会增加某种安全性,这是不正确的,他们也错误地认为如果盐和哈希已被破解,就等于根本没有使用盐,这也不是事实。即使有盐和哈希,这也需要极大的计算量来测试每个盐对每个字典中的单词! - user1004499

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接