ChatGPT解决这个技术问题 Extra ChatGPT

为哈希隐藏盐的必要性

在工作中,我们有两种相互竞争的盐理论。我工作的产品使用用户名或电话号码之类的东西来加盐。本质上,对于每个用户来说都是不同的,但我们很容易获得。另一款产品为每个用户随机生成一个salt,并在用户每次更改密码时更改。然后在数据库中加密盐。

我的问题是第二种方法是否真的有必要?我可以从纯理论的角度理解它比第一种方法更安全,但从实用性的角度来看呢?现在要对用户进行身份验证,salt 必须未加密并应用于登录信息。

在考虑之后,我只是没有看到这种方法真正的安全收益。将盐从一个帐户更改为另一个帐户,即使攻击者知道如何快速确定每个帐户的值,仍然使某人尝试暴力破解散列算法非常困难。这是在假设密码足够强的情况下进行的。 (显然,找到一组密码的正确哈希值,其中它们都是两位数字,比找到正确的 8 位密码哈希值要容易得多)。我的逻辑是不正确的,还是我遗漏了什么?

编辑:好的,这就是为什么我认为加密盐真的没有实际意义的原因。 (让我知道我是否走在正确的轨道上)。

对于下面的解释,我们假设密码总是 8 个字符,salt 是 5,所有密码都由小写字母组成(这只是为了让数学更容易)。

每个条目使用不同的盐意味着我不能使用相同的彩虹表(实际上,如果我有一个足够大的大小,我可以使用,但我们暂时忽略它)。据我了解,这是真正的关键,因为要破解每个帐户,我必须重新发明轮子,可以说每个帐户。现在,如果我知道如何将正确的盐应用于密码以生成散列,我会这样做,因为盐实际上只是扩展了散列短语的长度/复杂性。所以我会减少我需要生成的可能组合的数量,以“知道”我的密码+盐从 13^26 到 8^26,因为我知道盐是什么。现在这使它变得更容易,但仍然非常困难。

因此,对盐进行加密。如果我知道盐是加密的,我不会先尝试解密(假设我知道它有足够的加密级别)。我会忽略它。而不是试图弄清楚如何解密它,回到前面的例子,我只生成一个更大的彩虹表,其中包含 13^26 的所有密钥。不知道盐肯定会减慢我的速度,但我认为它不会增加尝试首先破解盐加密的艰巨任务。这就是为什么我认为这不值得。想法?

这是一个链接,描述了密码在暴力攻击下可以保存多长时间:http://www.lockdown.co.uk/?pg=combi

好问题,凯文,非常及时。我无法评论安全性,但可以肯定的是,所有这些加密和解密都会对性能造成影响。
您不需要忽略大小合适的彩虹表 - 该表也使加密的盐没有实际意义,因为它可以解密加盐的哈希并再次用于解密原始哈希。好消息是,这张桌子可能需要几个世纪才能制作出来。
让我感动的是,我不完全确定这样大小的彩虹桌需要那么长时间才能制作出来。他是一个古怪的想法,使用像 Kraken 这样的分布式计算平台(真的就是这样)来生成它。那时需要多长时间?
@Kevin:SHA1 返回一个 40 个字符的十六进制字符串,因此有 40^16 个可能的返回值。假设一台计算机每秒可以计算 1000 个哈希,我计算出 100 万台计算机需要大约 100 亿年才能生成能够确定该大小字符串的彩虹表。
@tloach 有软件可以做峰值 5600M/s MD5 哈希和 2300M/s SHA1 哈希。 golubev.com/hashgpu.htm

e
erickson

隐藏盐是不必要的。

每个哈希都应该使用不同的盐。在实践中,这很容易通过从加密质量随机数生成器中获取 8 个或更多字节来实现。

previous answer of mine

Salt有助于阻止预先计算的字典攻击。假设攻击者有一个可能的密码列表。他可以对每个哈希值进行哈希处理,并将其与受害者密码的哈希值进行比较,看看是否匹配。如果列表很大,这可能需要很长时间。他不想在下一个目标上花费太多时间,所以他将结果记录在一个“字典”中,其中哈希指向其相应的输入。如果密码列表非常非常长,他可以使用彩虹表之类的技术来节省一些空间。但是,假设他的下一个目标将他们的密码加盐。即使攻击者知道盐是什么,他的预计算表也毫无价值——盐会改变每个密码产生的哈希值。他必须重新散列他列表中的所有密码,将目标的盐添加到输入中。每种不同的盐都需要不同的字典,如果使用了足够多的盐,攻击者将没有空间为所有盐存储字典。交易空间以节省时间不再是一种选择;攻击者必须回退到对他想要攻击的每个目标的列表中的每个密码进行哈希处理。所以,没有必要对盐保密。确保攻击者没有与该特定盐对应的预先计算的字典就足够了。

在考虑了更多之后,我意识到欺骗自己认为可以隐藏盐是危险的。最好假设盐不能被隐藏,尽管如此,将系统设计为安全的。我提供更详细的解释in another answer.

然而,NIST 最近的建议鼓励使用额外的秘密“盐”(我看到其他人称这种额外的秘密“胡椒”)。可以使用这个秘密作为盐来执行密钥推导的另一个迭代。这一轮不是增加对预先计算的查找攻击的强度,而是防止密码猜测,就像一个好的密钥派生函数中的大量迭代一样。如果与散列密码一起存储,此机密将毫无用处;它必须作为秘密进行管理,这在大型用户数据库中可能很困难。


隐藏盐是必要的,因为在获得哈希之前无法破坏哈希。这与 CWE-760 (cwe.mitre.org/data/definitions/760.html) 有关
@The Rook - 不,你误解了这个问题。它指的是使用可预测的盐。它没有说要保守盐的秘密。确实,如果不使用另一个秘密,你就不能真正保持盐的秘密……在这种情况下,你为什么不使用第二个秘密作为盐呢?将用户名用作盐是不好的,因为多个系统可能共享相同的用户名,因此为该特定盐构建表更值得。随机盐是最好的,但它们不需要保密。
@erickson,我认为您在这里混淆了术语。盐不会阻止字典攻击,除非它们被隐藏。很多盐都是公开储存的。而且,如果您知道盐,那么您的字典攻击只会在将盐附加到您的字典术语时减慢:) 盐可以防止 Rainbow 表查找.... 这非常快。如果攻击者知道你的盐,你就不会受到字典攻击的保护。如果攻击者不知道你的盐,你就可以免受字典攻击,他们必须使用暴力攻击。
@Ultratrunks 是的,我已经使用“预计算字典攻击”一词澄清了我关于这个主题的一些答案。比 Rainbow 表更通用,它指的是允许使用其哈希作为键反向查找明文的任何结构。无论您选择何种术语,我都明确解释说 salt 旨在击败 Rainbow 表和类似机制。您应该始终假设攻击者知道盐。如果可以保密,则无需对密码进行哈希处理。
V
Vinko Vrsalovic

这里的答案是问问自己,你真正想要保护的是什么?如果有人可以访问您的数据库,那么他们就可以访问加密的盐,并且他们可能也可以访问您的代码。有了这些,他们可以解密加密的盐吗?如果是这样,那么无论如何加密几乎没有用。盐确实可以做到这一点,因此如果它被入侵,就不可能形成一个彩虹表来一次性破解您的整个密码数据库。从这个角度来看,只要每个盐都是唯一的,就没有区别,那么您的盐或每个密码的加密盐都需要进行暴力攻击。


对这些概念有点陌生。因此,这可能看起来像一个幼稚的问题,但是如果您只为每个可能的密码尝试一种盐值组合,那么在知道每个密码的盐值的情况下形成彩虹表会不会更容易?
说 1000 个常用密码的 ranbow 表将以几乎与散列相同的速度破解它。唯一可行的方法是,如果您假设密码的分布是统一的..我们知道它们不是
不,他们不太可能同时访问数据库和源代码,并且源代码不应包含用于加密的应用程序机密。考虑 SQL 注入的攻击向量,或暴露的备份数据库。那些不授予对代码或加密密钥的访问权限。
C
Community

隐藏的盐不再是盐。是辣椒。它有它的用途。它不同于盐。

Pepper 是添加到密码 + salt 的密钥,它使散列成为 HMAC(基于散列的消息验证码)。有权访问散列输出和盐的黑客理论上可以暴力猜测将生成散列的输入(并因此在密码文本框中通过验证)。通过添加胡椒,您可以以加密随机方式增加问题空间,在没有严重硬件的情况下使问题变得难以解决。

有关胡椒的更多信息,请查看 here

另见hmac


g
gbarry

我对“盐”的理解是它使破解更加困难,但它并没有试图隐藏额外的数据。如果您试图通过使盐“保密”来获得更高的安全性,那么您实际上只需要加密密钥中的更多位。


B
Bill the Lizard

第二种方法只是稍微安全一点。盐可以保护用户免受字典攻击和彩虹表攻击。它们使雄心勃勃的攻击者更难破坏您的整个系统,但仍然容易受到针对您系统的一个用户的攻击。如果您使用公开可用的信息(例如电话号码),并且攻击者意识到了这一点,那么您已经为他们的攻击节省了一步。当然,如果攻击者获得了你的整个数据库、盐和所有东西,这个问题就没有实际意义了。

编辑:在重新阅读了这个答案和一些评论之后,我突然想到,一些混淆可能是由于我只比较了问题中提出的两个非常具体的案例:随机盐与随机盐。非随机盐。如果攻击者获取了您的整个数据库,那么使用电话号码作为盐的问题是没有实际意义的,而不是使用盐的问题。


它们如何防止字典攻击?
通过强制攻击者为每个密码+盐组合创建一个新字典。没有盐,一个字典可以用于你的整个密码表。
“当然,如果攻击者获得了你的整个数据库、盐和所有东西,这个问题就没有实际意义了。”这不是盐被加密的原因吗?
@Bill:你刚刚描述了一张彩虹桌。字典攻击是我使用普通单词并尝试对其进行身份验证的地方。这是一种蛮力,答案空间大大减少。没有哈希可以抵御蛮力。
我从未听说过这种做法,但我不是安全专家。加密独特的盐似乎会增加一层额外的保护,防止彩虹表攻击。
A
Anon

...诸如用户名或电话号码之类的东西来加盐。 ...我的问题是第二种方法是否真的有必要?我可以从纯理论的角度理解它比第一种方法更安全,但是从实用性的角度来看呢?

从实际的角度来看,盐是一个实现细节。如果您改变了收集或维护用户信息的方式——使用您的确切示例,用户名和电话号码有时会发生变化——那么您可能已经损害了您的安全性。您是否希望这种面向外部的变化产生更深层次的安全问题?

停止要求每个帐户都有电话号码是否需要进行完整的安全审查,以确保您没有打开这些帐户导致安全漏洞?


更不用说您是否使用了一些任意位的用户信息,当他们更改该信息时,您需要他们再次输入密码,以便您可以使用新盐再次对其进行加密。
C
Charles Faiga

这是一个简单的示例,说明为什么每个哈希使用相同的盐是不好的

考虑下表

UserId  UserName,   Password
     1  Fred       Hash1 =  Sha(Salt1+Password1)    
     2  Ted        Hash2 =  Sha(Salt2+Password2)    

情况 1 当 salt 1 与 salt2 相同 如果 Hash2 被 Hash1 替换,那么用户 2 可以使用用户 1 的密码登录

情况 2 当 salt 1 不一样 salt2 如果 Hash2 替换为 Hash1 则 user2 无法使用用户 1 的密码登录。


我们没有为每个帐户使用相同的哈希,我们为每个哈希使用相同类型的信息。例如,帐户的盐是帐户的电话号码等。
我知道这是很久以后的事了,但是……你不能依靠盐来抵御这种类型的攻击。我们必须假设攻击者知道除了秘密(即密码)之外的有关身份验证系统的所有信息。因此我们必须假设攻击者知道a)我们使用什么作为盐(大多数情况下它以明文形式存储在同一个数据库和表中)和b)我们如何使用盐进行散列(即附加,散列两次, ETC)。如果用户有能力切换哈希,那么我们必须假设他们也可以切换盐。盐在这里无济于事。
P
Patrick McElhaney

有两种技术,具有不同的目标:

“盐”用于使两个原本相等的密码以不同的方式加密。这样,入侵者就不能有效地使用字典攻击来攻击整个加密密码列表。

在散列消息之前添加(共享)“秘密”,因此入侵者无法创建自己的消息并让它们被接受。


R
Russell Hankins

我倾向于隐藏盐。我使用 10 位盐,方法是在对密码进行散列之前将 1 到 1024 的随机数添加到密码的开头。在将用户输入的密码与哈希值进行比较时,我从 1 循环到 1024 并尝试所有可能的 salt 值,直到找到匹配项。这需要不到 1/10 秒的时间。我从 PHP password_hashpassword_verify 中得到了这样做的想法。在我的示例中,10 位盐的“成本”是 10。或者从另一个用户所说的,隐藏的“盐”被称为“胡椒”。盐在数据库中未加密。被强行逼出来了这将使彩虹表需要将散列反转 1000 倍。我使用 sha256 是因为它速度快,但仍然被认为是安全的。


因此,如果我的密码是“345678”,而您添加的随机盐恰好是“12”。如果有人输入“45678”作为我的密码。这在很多方面似乎都是错误的。
我猜罗素汉金斯的意思是在 1 到 1024 之间添加一个随机数,左边用零格式化;也就是说,如果随机盐为 12,则在前面加上“0012”
L
Lucas Oman

实际上,这取决于您尝试保护数据的攻击类型。

每个密码的唯一盐的目的是防止对整个密码数据库的字典攻击。

为每个密码加密唯一的盐将使破解单个密码变得更加困难,是的,但您必须权衡是否真的有很多好处。如果攻击者通过蛮力发现这个字符串:

Marianne2ae85fb5d

哈希到存储在数据库中的哈希,真的很难弄清楚哪一部分是通行证,哪一部分是盐?


如果有人暴力破解了如此不可能猜到的密码,我会说你无论如何都会被冲洗掉,因为显然他们拥有甚至没有人想到的技术。