小编典典

最佳实践:Salting & Peppering 密码?

all

我遇到了一个讨论,在其中我了解到我一直在做的实际上并不是对密码进行加盐,而是对密码进行撒粉,并且我已经开始使用以下功能进行这两种操作:

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

忽略选择的哈希算法(我希望这是对椒盐的讨论,而不是特定的算法,但我使用的是安全的算法),这是一个安全的选项还是我应该做一些不同的事情?对于那些不熟悉这些条款的人:

  • salt 是一个随机生成的值,通常与字符串一起存储在数据库中,旨在使使用哈希表无法破解密码。由于每个密码都有自己的盐,因此必须对它们进行单独的暴力破解才能破解它们;但是,由于盐与密码哈希一起存储在数据库中,因此数据库泄露意味着两者都丢失。

  • pepper 是与数据库分开存储的站点范围的静态值(通常在应用程序的源代码中硬编码),旨在保密。使用它是为了使数据库的妥协不会导致整个应用程序的密码表是暴力破解的。

有什么我遗漏的东西吗?在我的密码上加盐和撒盐是保护用户安全的最佳选择吗?这样做有任何潜在的安全漏洞吗?

注意:为了讨论的目的,假设应用程序和数据库存储在不同的机器上,不共享密码等,因此数据库服务器的破坏并不自动意味着应用程序服务器的破坏。


阅读 69

收藏
2022-08-24

共1个答案

小编典典

Peppers的明显优势

Peppers应该使哈希函数更安全似乎很明显。我的意思是,如果攻击者只获取您的数据库,那么您的用户密码应该是安全的,对吧?看起来合乎逻辑,对吧?

这就是为什么这么多人认为Peppers是个好主意的原因。这说得通”。

Peppers的现实

在安全和密码学领域,“有意义”是不够的。某些东西必须是可证明
有意义的,才能被认为是安全的。此外,它必须以可维护的方式实现。无法维护的最安全的系统被认为是不安全的(因为如果该安全性的任何部分发生故障,整个系统就会崩溃)。

Peppers既不适合可证明的模型,也不适合可维护的模型……

Peppers的理论问题

现在我们已经做好了准备,让我们看看Peppers有什么问题。

  • 将一个哈希输入另一个哈希可能很危险。

在您的示例中,您可以hash_function($salt . hash_function($pepper . $password)).

从过去的经验中我们知道,将一个哈希结果“输入”到另一个哈希函数会降低整体安全性。原因是这两个哈希函数都可能成为攻击的目标。

这就是为什么像PBKDF2这样的算法使用特殊操作来组合它们(在这种情况下是
hmac)。

关键是,虽然这没什么大不了的,但随便乱扔也不是一件小事。加密系统旨在避免“应该工作”的情况,而是专注于“设计为工作”的情况。

虽然这看起来纯粹是理论上的,但实际上并非如此。例如,Bcrypt
不能接受任意密码
。因此,传递bcrypt(hash(pw), salt)确实会导致比bcrypt(pw, salt)ifhash()返回二进制字符串更弱的散列。

  • 反对设计

bcrypt(和其他密码散列算法)的设计方式是使用盐。Peppers的概念从未被引入。这似乎是一件小事,但事实并非如此。原因是盐不是秘密。它只是一个攻击者可以知道的值。另一方面,根据定义,Peppers是密码学的秘密。

当前的密码散列算法(bcrypt、pbkdf2 等)都被设计为只接受一个秘密值(密码)。根本没有研究在算法中添加另一个秘密。

这并不意味着它不安全。这意味着我们不知道它是否安全。安全和密码学的一般建议是,如果我们不知道,那就不知道。

因此,在算法被密码学家设计和审查以用于秘密值(Peppers)之前,当前的算法不应该与它们一起使用。

  • 复杂性是安全的敌人

信不信由你,复杂性是安全的敌人。制作一个看起来很复杂的算法可能是安全的,也可能不是。但是它不安全的可能性非常大。

Peppers的重大问题

  • 它不可维护

您对Peppers的实现排除了旋转Peppers键的能力。由于胡椒用于单向函数的输入,因此您永远不能在值的生命周期内更改胡椒。这意味着你需要想出一些奇怪的技巧来让它支持密钥轮换。

这是 非常 重要的,因为每当您存储加密机密时都需要它。没有一种机制来轮换密钥(定期,以及在违规之后)是一个巨大的安全漏洞。

而您当前的Peppers方法将要求每个用户要么通过轮换使他们的密码完全失效,要么等到他们的下一次登录轮换(这可能永远不会)......

这基本上使您的方法立即禁止。

  • 它要求您推出自己的加密货币

由于当前没有算法支持Peppers的概念,因此需要您编写算法或发明新的算法来支持Peppers。如果你不能立即明白为什么这是一件非常糟糕的事情:

任何人,从最无知的业余爱好者到最好的密码学家,都可以创建一个他自己无法破解的算法。

* [布鲁斯·施奈尔](http://www.schneier.com/blog/archives/2011/04/schneiers_law.html)

永远不要 推出自己的加密货币......

更好的方式

因此,在上面详述的所有问题中,有两种处理这种情况的方法。

  • 只使用现有的算法

如果您正确使用 bcrypt 或 scrypt(成本很高),那么除了最弱的字典密码之外的所有密码都应该在统计上是安全的。以成本 5 散列 bcrypt
的当前记录是每秒 71k 散列。以这种速度,即使是 6 个字符的随机密码也需要数年时间才能破解。考虑到我的最低推荐成本是 10,这将每秒哈希值减少了 32
倍。所以我们只讨论每秒 2200 个哈希值。以这种速度,即使是某些字典短语或修饰语也可能是安全的。

此外,我们应该在门口检查那些弱密码类别,不允许他们进入。随着密码破解越来越先进,密码质量要求也应该如此。它仍然是一个统计游戏,但有了适当的存储技术和强大的密码,每个人实际上都应该非常安全......

  • 在存储之前加密输出哈希

在安全领域中存在一种算法,旨在处理我们上面所说的一切。这是一个分组密码。这很好,因为它是可逆的,所以我们可以旋转密钥(耶!可维护性!)。这很好,因为它按设计使用。这很好,因为它没有给用户任何信息。

让我们再看看那条线。假设攻击者知道您的算法(这是安全所必需的,否则它是通过晦涩难懂的安全性)。使用传统的Peppers方法,攻击者可以创建一个哨兵密码,并且由于他知道盐和输出,他可以暴力破解Peppers。好吧,这是一个很长的镜头,但它是可能的。使用密码,攻击者一无所获。而且由于盐是随机的,因此哨兵密码甚至对他/她没有帮助。所以他们剩下的最好的就是攻击加密的形式。这意味着他们首先必须攻击您的加密哈希以恢复加密密钥,然后再攻击哈希。但是有
很多 关于密码攻击的研究,所以我们希望依靠它。

TL/DR

不要用Peppers。它们存在许多问题,有两种更好的方法:不使用任何服务器端机密(是的,没关系)和在存储之前使用块密码加密输出哈希。

2022-08-24