我了解散列和加盐的必要性,但我不明白如何将盐存储在同一个(可能受到破坏的)数据库中,因为整个散列是安全的。例如,我正在学习的一本书指示通过随机生成一个整数并使用 RNGCryptoServiceProvider 创建一个 byte[] 来为每个用户(好)创建一个唯一的哈希。这一切都很好,但是为了在登录时验证用户的密码,有必要从数据库(或其他文件)中读取唯一的盐。这是储存盐的安全方式吗?
5 回答
想象一下,你是一个坏人,你可以访问一个密码数据库。那里有很多信息,事情已经够糟糕的了。对我们其他人来说,唯一的好消息是这最终是死数据。你真正想要的是访问活生生的、正在运行的系统,以及让该系统做任何你想做的事情的能力……尤其是如果没有人知道你在其中。
这是诀窍。要获得访问权限,您不需要真正发现真正的密码:您只需要找到一些导致相同哈希的文本值。更糟糕的是,您不需要暴力破解结果。那里有一些有用的表格,可让您快速找到会产生所需散列的文本。
因此,盐的目的是为这些预先计算的表添加皱纹。您可能有一个可以产生特定哈希的值,但您预先计算的“彩虹表”不考虑盐。盐完全改变了哈希。现在你又回到了需要暴力破解个人密码的问题上,如果系统设计者使用了可能需要数年时间的好的加密算法。
这里的好处是盐有这种影响,即使你知道它的价值。即使盐是公开的,只要有一个每个用户的盐,就会破坏攻击者对您的密码数据库使用彩虹表攻击的能力。
(不过,共享盐将允许攻击者开始使用通用密码等运行破解解决方案,并开始将东西扔在墙上……将哈希结果与所有用户进行比较,看看会发生什么)。
这是安全的,因为访问盐不会使攻击者更容易逆转散列过程。给定密码、盐和哈希,您可以快速检查三元组是否正确。但是,您不能使用盐的知识来帮助您获取密码。
回想一下,首先需要盐的原因是为了避免相同的密码产生相同的哈希值。如果没有盐,攻击者将能够散列“彩虹表”,并根据编码字典检查散列。
加盐增加了对受损数据库执行离线攻击的难度。虽然拥有足够资源的攻击者最终会破解您的所有密码,但加盐通过两种方式使其更难:
- 基于通用密码(称为彩虹表)的预先计算的哈希列表不能应用于加盐密码(至少在不考虑所有盐的情况下)
- 破解一个加盐密码不会提供任何其他密码的信息(例如,两个密码是否相同)。
难度的增加允许有更多的时间来发现和减轻受损数据库的影响。
您可以通过分离散列和盐来获得更好的安全性,因为没有盐的攻击者将不得不暴力破解盐。然而,在实践中,实现这种分离既困难又麻烦,如果攻击者拥有该级别的访问权限,他很可能能够获得盐和密码。
Salting 通过在预先制作的表格中查找哈希来防止破解哈希。如果攻击者知道盐,它不会在这个攻击向量中帮助他们,因为他们仍然需要暴力破解密码。
每个用户使用不同的盐意味着他们必须花费所有资源来为单个用户强制匹配哈希。因此,它不一定是“安全的”,而是要破解整个数据库非常困难(不可能?),即使破解一个数据库也需要大量的努力。
您可以将每条记录的盐与全局盐结合起来,这样即使您的数据库遭到破坏,它们仍然是缺乏可行蛮力的一个元素。
我会说两者都去 - 毕竟不会受伤......