最佳做法:腌制和密码密码?
我遇到了一个讨论,在这个讨论中,我了解到我一直在做的事实上并不是叮passwords密码,而是狠狠地诅咒他们,而我从一开始就开始用这样的功能来做:
hash_function($salt.hash_function($pepper.$password)) [multiple iterations]
忽略选择的散列算法(我希望这是盐和辣椒的讨论,而不是特定的算法,但我使用安全的算法),这是一个安全的选择,还是应该做一些不同的事情? 对于那些不熟悉这些术语的人:
salt是随机生成的值,通常与数据库中的字符串一起存储,旨在使用哈希表来破解密码。 由于每个密码都有它自己的盐,所以他们都必须单独强暴以破解它们; 然而,由于salt与密码哈希存储在数据库中,数据库的妥协意味着两者都将丢失。
胡椒是一个站点范围的静态值,与数据库分开存储(通常在应用程序的源代码中进行硬编码),这是为了保密。 它的使用是为了妥协的数据库不会导致整个应用程序的密码表是暴躁的。
有什么我不知道的东西,并且腌制和胡椒粉我的密码是保护我的用户安全的最佳选择? 这样做有没有潜在的安全缺陷?
注意:为了讨论的目的,假设应用程序和数据库存储在不同的机器上,不要共享密码等,因此违反数据库服务器并不意味着会违反应用程序服务器。
好。 看到我需要一遍又一遍地写这些,我会对胡椒单独做一个最后的典型回答。
辣椒的明显上升
似乎很明显,辣椒应该使哈希函数更安全。 我的意思是,如果攻击者只能得到你的数据库,那么你的用户密码应该是安全的,对吧? 看起来合乎逻辑,对吗?
这就是为什么很多人认为辣椒是一个好主意。 这说得通”。
辣椒的现实
在安全和密码领域,“有意义”是不够的。 为了使它被认为是安全的,某些东西必须是可证明的并且是有意义的。 此外,它必须以可维护的方式实施。 无法维护的最安全的系统被认为是不安全的(因为如果该安全性的任何部分发生故障,整个系统就会崩溃)。
辣椒既不适合可证实的也不适合可维护的模型......
辣椒的理论问题
现在我们已经开始了舞台,让我们看看辣椒有什么问题。
将一个散列填入另一个散列可能是危险的。
在你的例子中,你做了hash_function($salt . hash_function($pepper . $password))
。
根据以往的经验,我们知道将一个散列结果“喂入”另一个散列函数会降低总体安全性。 原因是这两个散列函数都可能成为攻击的目标。
这就是为什么像PBKDF2这样的算法使用特殊操作来组合它们(在这种情况下是hmac)。
问题是,虽然这不是什么大问题,但抛开它也不是一件小事。 加密系统旨在避免“应该工作”的情况下,而是专注于“设计到工作”的情况。
虽然这看起来纯粹是理论上的,但实际上并非如此。 例如,Bcrypt不能接受任意密码。 因此bcrypt(pw, salt)
如果hash()
返回一个二进制字符串bcrypt(hash(pw), salt)
那么传递bcrypt(hash(pw), salt)
确实会导致比bcrypt(pw, salt)
更弱的散列。
反对设计工作
bcrypt(和其他密码哈希算法)的设计方式是使用盐。 胡椒的概念从未被引入。 这可能看起来像一个小事,但事实并非如此。 原因是盐不是秘密。 这只是一个攻击者可以知道的价值。 另一方面,胡椒根据定义是密码秘密。
目前的密码散列算法(bcrypt,pbkdf2等)都被设计为只能带一个秘密值(密码)。 根本没有研究在算法中增加另一个秘密。
这并不意味着它不安全。 这意味着我们不知道它是否安全。 而安全和密码学的一般建议是,如果我们不知道,事实并非如此。
因此,直到算法被密码学家设计和审查以用于秘密值(辣椒),目前的算法不应该与它们一起使用。
复杂性是安全的敌人
信不信由你,复杂性是安全的敌人。 制作一个看起来很复杂的算法可能是安全的,或者它可能不是。 但是这个机会很重要,因为它不安全。
辣椒的重大问题
这是不可维修的
你的辣椒的实施排除了旋转辣椒钥匙的能力。 由于胡椒粉用于单向函数的输入,所以永远不能改变胡椒粉的值。 这意味着你需要拿出一些不可思议的黑客来支持重要的轮换。
这是非常重要的,因为无论何时您存储加密密码都需要。 没有一个机制来轮换键(定期,并在违规之后)是一个巨大的安全漏洞。
而你目前的胡椒方法将要求每个用户都要么通过轮换使他们的密码完全失效,要么等到他们下一次登录时旋转(可能永远不会)...
这基本上使你的方法立即停止。
它需要你滚动你自己的密码
由于目前的算法不支持胡椒的概念,因此它需要您编写算法或创建新的算法来支持胡椒。 如果你不能立即明白为什么这是一件非常糟糕的事情:
任何人,从最无知的业余人员到最好的密码专家,都可以创建一个他自己无法破解的算法。
永远不要推出自己的加密...
更好的方式
所以,在上面详述的所有问题中,处理这种情况有两种方式。
只要使用算法,因为它们存在
如果您正确使用bcrypt或scrypt(成本很高),除了最薄弱的字典密码之外,所有字符密码都应该是统计安全的。 目前以成本5进行散列加密的记录是每秒71k次散列。 那样的话,即使是6个字符的随机密码也需要数年时间才能破解。 考虑到我的最低建议成本是10,那么每秒的哈希数就会减少32倍。所以我们只会谈到每秒大约2200次哈希。 以这样的速度,即使是一些字典短语或修改可能是安全的。
另外,我们应该在门口检查那些弱类的密码并且不允许他们进入。由于密码破解变得更加先进,密码质量要求也应该如此。 这仍然是一个统计游戏,但具有适当的存储技术和强大的密码,每个人都应该几乎是非常安全的...
在存储之前加密输出散列
安全领域中存在一种算法,旨在处理我们上面所说的一切。 这是一个分组密码。 这很好,因为它是可逆的,所以我们可以旋转键(耶!可维护性!)。 这很好,因为它是按照设计使用的。 这很好,因为它给用户没有任何信息。
我们再来看看那条线。 假设攻击者知道你的算法(这是安全需要的,否则它通过默默无闻的安全性)。 使用传统的胡椒方法,攻击者可以创建一个哨兵密码,并且由于他知道盐和输出,他可以强制胡椒。 好吧,这是一个很长的一步,但它是可能的。 用密码,攻击者什么也得不到。 由于盐是随机的,一个哨兵密码甚至不会帮助他/她。 所以他们留下的最好的办法是攻击加密的表单。 这意味着他们首先必须攻击你的加密哈希以恢复加密密钥,然后攻击哈希。 但是对攻击密码的研究有很多 ,所以我们想依靠这个。
TL / DR
不要使用辣椒。 他们有很多问题,有两种更好的方法:不使用任何服务器端秘密(是的,没关系),并在存储之前使用分组密码加密输出哈希。
拳头我们应该谈论辣椒的确切优势 :
一个典型的场景是SQL注入,丢弃备份,丢弃的服务器......这些情况并不罕见,听起来并不常见,而且通常不受您的控制(服务器托管)。 如果你使用...
...强密码受到很好的保护。 在这些条件下暴力强制密码几乎是不可能的,即使盐是已知的。 问题是弱密码,它是暴力字典的一部分,或者是它们的衍生物。 字典攻击会非常快速地显示这些信息,因为您只测试最常见的密码。
第二个问题是如何使用胡椒粉 ?
通常推荐使用胡椒的方法是在将密码传递给哈希函数之前将密码和胡椒组合在一起:
$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);
还有另一种更好的方法:
$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);
这不仅允许添加一个服务器端的秘密,它还允许交换$ serverSideKey,如果这是必要的。 这个方法涉及更多的工作,但是如果代码一旦存在(库),没有理由不使用它。
盐和胡椒点是增加预先计算的密码查找的成本,称为彩虹表。
一般来说,试图找到单个散列的冲突很难(假设散列是安全的)。 但是,使用短哈希值,可以使用计算机将所有可能的哈希值生成到硬盘上。 这被称为彩虹表。 如果你创建了一个彩虹表,你就可以进入这个世界,并快速找到任何(未加注的unpeppered)散列的合理密码。
胡椒粉的要点是让彩虹桌必须破解你的密码列表。 因此浪费更多时间在攻击者构建彩虹桌上。
然而盐的要点是要让每个用户的彩虹表对用户来说是唯一的,这进一步增加了攻击的复杂性。
真正的计算机安全性几乎不会使它(数学)变得不可能,只是在数学上和物理上不切实际(例如在安全系统中,它将采用宇宙中的所有熵(以及更多)来计算单个用户的密码)。
链接地址: http://www.djcxy.com/p/21535.html上一篇: Best Practices: Salting & peppering passwords?
下一篇: Difference between Hashing a Password and Encrypting it