在创建密码时,我们应该如何关注暴力攻击?

How concerned should we be about brute force attacks when creating passwords?

暴力破解在现实世界中有效吗?几乎我曾经使用过的每项需要密码的服务都有某种类型的保护,以防止尝试多个密码。另外,这如何转化为数据加密?

蛮力a.k.a。详尽的密钥搜索 - 是一种可以对多种攻击向量起作用的方法

您所描述的是通过服务进行身份验证来攻击服务。这里的服务充当守门人,可以通过限制您的尝试等方式来防止攻击

然而,这只是系统的一个攻击向量:

如果攻击者通过其他方式获得对用户数据库的访问权限怎么办?他现在可以利用这些知识来访问服务吗?

如果上述服务的所有者愚蠢到可以存储明文密码……哎哟……但我们假设密码的存储方式至少使用一种单向函数,如哈希函数

让我们看看发生了什么变化...

在可用计算资源允许的情况下,我们可以在密码猜测方面进行尽可能多的尝试...

这里唯一剩下的看门人就是猜测密码的复杂性

如果我们只需要检查 value == hash(password),我们可以很容易地看到除了暴力破解之外还有其他有效的攻击方法...

但是你特别要求暴力破解,所以让我们假设我们的密码是加盐的...

value == hash(password,salt) ...不再有彩虹表...但这仍然很糟糕,因为我们可以非常快速地计算并并行化...剩下的限制因素是硬件...如果我们投入大量(租用?...被黑客入侵?)具有足够内核/GPU 的数字运算系统...我们通过暴力破解密码的速度有多快? ...让我们在这里做一些数学运算...

假设我们有一个系统可以完成我们的工作……每秒大约进行 1,000,000 次密码猜测……假设我们的密码的熵约为 42 位……这大约是一个 9 个字母的小写密码。 .. 需要多长时间?

~51 天,如果攻击者知道允许的字符池(在我们的例子中是较低的 alpha),则可以保证肯定的猜测

你可以假设在 50% 的时间之后,正确猜测的概率是 50% 所以...不会很长...

但情况变得更糟了……我们假设一台机器……如果我们 buy/rent/hack 更多,它会扩展吗?当然可以……假设有 10,000 台机器……

我们可以简单地除以 10k ...我们大约减少了 7 分 21 秒...

从云提供商那里租用 10k 台机器 10 分钟需要多少钱? ...作为一个例子(我们没有指定哈希函数的复杂性,所以这个例子可能不在每秒猜测的范围内,但你会看到这是怎么回事)... a1.xlarge亚马逊 EC2 按需实例的成本约为每小时 10 美分……我们需要它……10 分钟……所以除以 6……我们需要 10k 个节点……大约 170 美元……让我们汇总 ... 200 美元作为粗略估计

所以...如果我们想租用计算资源,则可以以相对较少的钱获得大量计算资源...现在想想捕获计算资源的恶意软件

所以......坏人方面拥有所有计算资源......我们能做什么?

我们可以让猜测变得更难......

如果我们将密码复杂性从上面的 42 位增加到...让我们说下部和上部字母数字和 16 个字符的长度...那是大约 96 位的熵...我们的小机器有每秒 1,000,000 次猜测大约需要 2.5 万亿年才能找到我们的密码(保证......如果它没有发生故障,有足够的能量,并且你找到了一种方法让它在几十亿年的太阳结束时幸存下来...... . 但那是另一个故事)

但回到现实世界..我们采用另一个云设置,每秒可以猜测 100,000,000,000,000 个密码......是我们之前计算的 10k 台机器大小的 10k 倍......这将花费我们 2500 万年有保证的命中……在 50% 的时间后可能成功……那么为什么这不能抵消那些额外的 54 位熵的增加? ...呈指数增长...每多一点,工作量就会翻倍...

除了增加熵之外,我们还可以做的另一件事是增加猜测的计算复杂度

如果我们像 hash(hash(hash(...))) 那样将我们的散列函数链接可变的轮数,我们可以增加计算结果所需的时间...

对于常规登录,登录需要 10 毫秒还是 250 毫秒并不重要,但对于攻击者来说,这种差异意味着他必须提供 25 倍的计算资源,或者需要 25 倍的时间...不像我们的熵增加那么强大,但仍然......这是一个可衡量的效果,对我们来说成本非常低

当谈到数据加密时,我们通常不谈论密码,而是谈论加密密钥……几个字节的熵……在这个级别上,它与上面的计算基本相同……大约在 80 到90 位相当困难且昂贵......大约 40 位......哎呀它是开放的......

有趣的是,当您必须使用密码来加密某些内容时...如何从密码中获取所需的密钥字节?散列?可能...但是如何?

好事是......其他人在我们面前遇到了同样的问题......这导致了像 PBKDF2(密码派生密钥派生函数......你可以看到它作为具有可变长度输出的散列函数......它创建一个伪随机比特流,你可以根据需要获取尽可能多的比特......通常是对称密码的密钥大小)

PBKDF2 有一个 round 参数来增加计算时间...所以基本上...和上面的完全一样