实用建议
- 使用 Argon2id。
- 您使用的内存越多,与您的 CPU 相比,攻击者的优势就越小。
- 相对于 2021 年 GPU 的绝对数量:
- 128 MiB 是相当安全的(如果可以的话,不要犹豫,选择 2 GiB 或更多!),
- 32 MiB 是合理的,并且
- 4 MiB 明显偏低。
- 对抗 ASIC,你肯定想走得更高。如果您的对手有 Argon2 ASIC 的预算,那么将几 GB 的常规 RAM 用于密码散列也不是什么奢侈的事情。同样有效的是添加多因素身份验证并强制执行全球唯一密码(检查公共违规行为)。
对于实力较弱的对手,有趣的是,破解软件似乎落后了,截至 2021 年,仍然没有好的 Argon2 破解器可用。Bcrypt 和 scrypt (反过来)比 PBKDF2-class* 算法要好得多,这主要是因为它们的设计更好,但也因为在优化这些强哈希方面投入的精力较少,尤其是在使用 scrypt 的内存大于 16 MiB 时。
* 任何对散列函数进行简单迭代的东西,所以这包括许多开发人员使用的定制设计(d)。Bcrypt 处于更高级别,因为“ Bcrypt 恰好严重依赖于对在整个算法执行过程中不断更改的表的访问。这在 PC 上非常快,在 GPU 上则更不用说了,在 GPU 上共享内存并且所有内核都竞争用于控制内部存储器总线。因此,与攻击者使用 PBKDF2 或类似设计所获得的相比,攻击者从使用 GPU 获得的提升要小得多。 ”——Thomas Pornin 在是否有安全专家推荐 bcrypt 作为密码贮存?
破解内存硬散列
今天发布了一个 hashcat 版本(当我结束我的研究时),它具有更好的 scrypt 支持(另一种内存硬算法)。我一直在使用 RX 5700 GPU 进行测试,按照今天的高价计算,它的价格似乎接近 1000 美元,并且具有 8 GB 的 VRAM。今天早些时候尝试用 hashcat 破解 scrypt 哈希,它已经在 16 MiB 时出错(N=16×1024,r=8,p=1);通过新的更新,我现在可以破解 scrypt 哈希值高达数百兆字节的内存。hashlib.scrypt在 64 MiB 时,hashcat 比使用 OpenSSL 实现的Python 快 17 倍。总比没有好,但相比之下,PBKDF2 在相同的 CPU/GPU 组合上获得了 1000 倍的加速。(而且,据记录,Bcrypt 从 CPU 到 GPU 的速度也提高了 17 倍。)
对于 Argon2,我能找到的最快的破解软件是 CPU 实现。我能找到的唯一看起来不错的GPU 实现在出错之前最多可以分配 434 MiB,但比 PHP 的实现慢(如果我没记错的话,使用 libsodium),不管你使用了多少内存。而且 PHP 也不限制内存使用,它会很高兴地在几秒钟内为您计算 Argon2 和 13 GiB 的 RAM。
理论上
您应该能够分配与 GPU 一样多的内存,即使实际上没有免费的破解软件真正支持它。无论哪种方式,通过要求不断访问主内存而不是能够使用核心本地寄存器,您确实限制了 GPU 的效率:它的内存是全部共享的并且带宽是有限的。CPU 也有同样的限制,但这只是将其置于更公平的竞争环境中。GPU 带宽仍超过 CPU*,但处于同一数量级。
ASIC 是一种下一级攻击,我在写问题时并不担心。但无论如何我现在已经研究过了,GPU 似乎在今天的软件状态下基本上无效,几乎不管你使用什么设置,所以我们不妨考虑一下。
生产 ASIC 的成本似乎主要取决于您需要的内存量。Argon2论文(第 2.1 节)将其描述为:
我们的目标是最大限度地提高 ASIC 密码破解的成本。可以有不同的方法来衡量这个成本,但我们转向最流行的方法之一——时区乘积 [4, 16]。
[...]
- 50-nm DRAM 实施 [10] 每 GByte 占用 550 mm²;
- 65-nm 工艺中的 Blake2b 实现大约需要 0.1 mm²(使用 [11] 中的 Blake-512 实现);
它并没有用太多的话来说明,而且论文只谈到了表面积而不是成本,但听起来增加 ASIC 上的 RAM 容量比增加计算能力要昂贵得多。
所以在挑选 Argon2id 参数方面,正确的顺序是:
- 首先以时间成本参数 1** 尽可能增加内存使用量。
- 在不降低先前参数的情况下尽可能增加并行度,直到达到系统的核心数。
- 在不降低先前参数的情况下,尽可能增加时间成本参数。
“尽可能”的意思是:直到它耗尽系统资源(RAM、内核)或者直到它变得比你的用户有耐心的慢。
如果您调整的唯一参数是内存使用情况,这并不奇怪。它可能已经变得很慢了。
并行有点复杂。
在 Argon2 中,设置 p=2 时的两部分可以并行计算,因此如果您的内存参数适合缓存或者如果您使用的可用内存带宽不到一半,则 p=2 在您的 CPU 上花费的时间不应超过 p=1,但应该更强。这似乎在实践中有效:在 PHP(使用 libsodium)中进行测试,增加“线程”设置显然要快得多。(请注意,本文将其称为“通道”以设置“并行”,然后 PHP 将其称为“线程”......)为了确保您充分利用硬件(使 GPU/ASIC 竞争相对困难),建议在增加时间成本参数之前将此设置设置得更高(因为时间成本参数无非是在指定的内存量上多次运行算法)。
加密货币在其论文或RFC中并没有多说,但似乎具有相同的功能。在实践中,似乎 scrypt 实现不执行多线程:Hashcat 和 OpenSSL 似乎只需要p倍的时间。还有一个scrypt JavaScript 实现,它“可以在浏览器中进行多线程”,但这似乎只适用于 p=1 和 p=2(同样快)的 Linux 上的 Firefox 或 p=2 和 p 的 Windows 上的 Firefox =4(同样快)。其他值(例如 Windows 上的 Firefox 中的 p=1 和 p=2)线性变慢,其他浏览器(例如ChromiumEdge)似乎根本不支持它。您可能希望寻找支持此功能的实现以获得更强的散列,或者改用 Argon2。
*“在 NVIDIA Tesla K20X 上,CUDA 实现可以达到大约 40-60 GiB/s [...]。相比之下,快速的 Intel Xeon 处理器只能达到大约 10 GiB/s。” --- Panos Kal.,2017 年,关于“在 GPU 上解决比在 CPU 上花费更长的时间来解决的密码算法”
** 由于内存是最重要的,因此时间成本参数最初应设置为 1。这不是不安全的:Argon2 作者在Argon2 论文第 6.4 节中写道“同样,T 没有“不安全值” ”,加密论坛研究组写道“ Argon2id [with] t=1 and 2GiB memory is [ ...] 建议作为所有环境的默认设置。[设置] t=3 和 64 MiB 内存 [...] 建议作为内存受限环境的默认设置。 "
问题的怪癖
问题的措辞表明作者的误解。
提议的陈述“ [X MiB of memory] 已经使普通消费者 GPU 完全无效”是完全错误的,因为 GPU 内核可以处理 GPU 拥有的所有内存,但在实际意义上也是正确的,因为当前的实现似乎打破了早在接近 GPU 的实际内存限制之前。给这个值加上一个数字,1 GiB 似乎足以触发这种效果,但解决这个问题是软件问题,而不是硬件限制。
另一种说法“由于内存需求增加而导致 GPU 的减速是线性比例。 ”也是错误的,因为这无法参数化内存带宽差异。并非您可以通过接近破解硬件的内存量来缩小速度差距。另一方面,使用过低的内存参数不会使 CPU 的内存带宽饱和,并为 GPU 破解者提供比较优势,因此(意外地)这里也有一个真理的核心。
作为用户
请记住,您始终可以使用强大且唯一的密码来保护自己的帐户。如果您的密码是 15 个随机字符(从 {az, AZ, 0-9} 中挑选),即使是最愚蠢的密码哈希也是(量子前)安全的。如果您不重复使用密码,那么密码是否被破解也无关紧要。密码管理器可以帮助您生成和管理这些密码。