我遇到了一个讨论,其中我了解到我一直在做的事实上并没有腌制密码而是给它们加油,而且我已经开始使用以下功能:
hash_function($salt.hash_function($pepper.$password)) [multiple iterations]
忽略所选的哈希算法(我希望这是对盐和辣椒的讨论,而不是特定的算法,但我使用的是安全算法),这是一个安全的选择还是我应该做一些不同的事情?对于那些不熟悉这些条款的人:
-
A salt 是一个随机生成的值,通常与数据库中的字符串一起存储,旨在使得无法使用哈希表破解密码 . 由于每个密码都有自己的盐,因此必须对它们进行单独强制攻击才能破解它们;但是,由于salt使用密码哈希存储在数据库中,因此数据库泄露意味着丢失两者 .
-
A pepper 是与数据库分开存储的站点范围的静态值(通常在应用程序_1041840的密码表中进行硬编码,以便强制执行 .
有什么我缺少的,并且正在腌制和密封我的密码是保护用户安全的最佳选择吗?这样做有没有潜在的安全漏洞?
注意:为了讨论的目的,假设应用程序和数据库存储在不同的计算机上,不共享密码等,因此违反数据库服务器并不意味着违反应用程序服务器 .
4 回答
好 . 看到我需要写一下这个over和over,我将仅就胡椒做一个最后的规范回答 .
辣椒的明显好处
很明显辣椒应该使哈希函数更安全 . 我的意思是,如果攻击者只获取您的数据库,那么您的用户密码应该是安全的,对吧?似乎合乎逻辑,对吧?
这就是为什么很多人都认为辣椒是个好主意的原因 . 这说得通” .
辣椒的现实
在安全和加密领域,"make sense"是不够的 . 必须证明某些事情是有道理的,以便将其视为安全 . 此外,它必须以可维护的方式实现 . 无法维护的最安全系统被认为是不安全的(因为如果该安全性的任何部分发生故障,整个系统就会崩溃) .
辣椒既不适合可证明的模型,也不适合可维护的模型......
辣椒的理论问题
现在我们已经开始了舞台,让我们来看看辣椒有什么问题 .
在您的示例中,您执行
hash_function($salt . hash_function($pepper . $password))
.我们从过去的经验中知道,“将一个哈希结果”加入另一个哈希函数会降低整体安全性 . 原因是两个哈希函数都可以成为攻击目标 .
这就是像PBKDF2这样的算法使用特殊操作来组合它们的原因(在这种情况下是hmac) .
关键在于虽然这不是什么大不了的事情,但抛出它也不是一件小事 . 加密系统旨在避免“应该工作”的情况,而是专注于“设计工作”的情况 .
虽然这看似纯粹是理论上的,但实际上并非如此 . 例如,Bcrypt cannot accept arbitrary passwords . 因此,如果
hash()
返回二进制字符串,那么传递bcrypt(hash(pw), salt)
确实会导致比bcrypt(pw, salt)
更弱的哈希 .设计bcrypt(和其他密码哈希算法)的方法是使用salt . 辣椒的概念从未被引入 . 这可能看起来像是一件小事,但事实并非如此 . 原因是盐不是秘密 . 它只是攻击者可以知道的值 . 另一方面,胡椒的定义是密码秘密 .
当前的密码哈希算法(bcrypt,pbkdf2等)都设计为只接受一个秘密值(密码) . 尚未研究在算法中添加另一个秘密 .
这并不意味着它不安全 . 这意味着我们不知道它是否安全 . 安全性和密码学的一般建议是,如果我们不知道,那就不是 .
因此,在密码学家设计和审查算法以使用秘密值(辣椒)之前,不应将当前算法与它们一起使用 .
信不信由你,Complexity Is The Enemy Of Security . 制作看起来复杂的算法可能是安全的,也可能不是 . 但是,它的安全性非常大 .
辣椒的重大问题
您对辣椒的实施排除了旋转辣椒键的能力 . 由于胡椒用于单向函数的输入,因此您永远不能在值的生命周期内更改胡椒 . 这意味着你需要想出一些难以捉摸的黑客来支持关键轮换 .
这是 extremely 很重要,因为每当您存储加密机密时都需要它 . 没有机制来轮换密钥(定期和违规后)是一个巨大的安全漏洞 .
而你目前的胡椒方法需要每个用户都有他们的密码完全通过轮换无效,或等到下次登录时轮换(可能永远不会)...
这基本上使你的方法立即禁止 .
由于当前没有算法支持胡椒的概念,它需要你编写算法或发明新算法来支持胡椒 . 如果你不能立即明白为什么这是一件非常糟糕的事情:
NEVER 滚动你自己的加密......
更好的方式
因此,在上面详述的所有问题中,有两种方法可以处理这种情况 .
如果您正确使用bcrypt或scrypt(成本很高),除了最弱的字典密码之外的所有密码应该在统计上是安全的 . 成本为5的哈希bcrypt的当前记录是每秒71k哈希 . 按照这个速度,即使是6个字符的随机密码也需要数年才能破解 . 考虑到我的最低建议成本是10,这会使每秒的哈希值降低32倍 . 所以我们每秒只能说约2200次哈希值 . 按照这个速度,即使是一些字典短语或修改也可能是安全的 .
此外,我们应该在门口检查那些弱类密码而不允许它们进入 . 随着密码破解变得更加先进,密码质量要求也应如此 . 它仍然是一个统计游戏,但通过适当的存储技术和强密码,每个人都应该非常安全......
在安全领域中存在一种算法,用于处理我们上面说过的所有内容 . 这是一个分组密码 . 这很好,因为它是可逆的,所以我们可以旋转键(耶!可维护性!) . 这很好,因为它是按设计使用的 . 它很好,因为它没有给用户任何信息 .
让's look at that line again. Let'说攻击者知道你的算法(这是安全所必需的,否则它很长,但它甚至可以帮助他/她 . 所以他们留下的最好的就是攻击加密的形式 . 这意味着他们首先必须攻击你的加密哈希以恢复加密密钥,然后攻击哈希 . 但是对密码的攻击有一个研究,所以我们要依赖它 .
TL / DR
不要使用辣椒 . 它们存在许多问题,有两种更好的方法:不使用任何服务器端密码(是的,没关系)并在存储之前使用块密码加密输出哈希 .
我们应该谈谈 exact advantage of a pepper :
典型的情况是SQL注入,丢弃备份,丢弃的服务器......这些情况并不像听起来那么罕见,而且通常不在您的控制之下(服务器托管) . 如果你用...
每个密码的唯一盐
像BCrypt这样的慢哈希算法
...强密码得到很好的保护 . 在这些条件下暴力强制密码几乎是不可能的,即使已知盐 . 问题是弱密码,它们是蛮力字典的一部分,或者是它们的派生 . 字典攻击会非常快速地显示,因为您只测试最常用的密码 .
第二个问题是 how to apply the pepper ?
通常推荐的应用胡椒的方法是在将密码和胡椒传递给散列函数之前将其组合:
还有另一种更好的方法:
这不仅允许添加服务器端密钥,还允许交换$ serverSideKey,如果有必要的话 . 这种方法需要更多的工作,但如果代码一旦存在(库),就没有理由不使用它 .
盐和胡椒的要点是增加预先计算的密码查找的成本,称为彩虹表 .
通常,尝试查找单个哈希的冲突很困难(假设哈希是安全的) . 但是,使用短哈希,可以使用计算机生成所有可能的哈希值,以查找到硬盘上 . 这被称为彩虹表 . 如果你创建了一个彩虹表,那么你可以进入这个世界,并快速找到任何(未加盐的未加工的)哈希的可用密码 .
辣椒的目的是使彩虹表成为破解你的密码列表所必需的 . 因此浪费更多时间在攻击者身上构建彩虹表 .
然而,盐的目的是使每个用户的彩虹表对用户来说是唯一的,这进一步增加了攻击的复杂性 .
真正意义上的计算机安全几乎从不使它(数学上)不可能,只是在数学上和物理上都是不切实际的(例如在安全系统中它会占用宇宙中的所有熵(以及更多)来计算单个用户密码) .
无法在源代码中看到存储硬编码值具有任何安全相关性 . 这是通过默默无闻的安全 .
如果黑客获得了您的数据库,他将能够开始强制您的用户密码 . 如果他设法破解了一些密码,那么黑客就不会花很长时间来识别你的胡椒 .