在讨论口令哈希时,经常看到「内存硬」这个说法:Argon2 是内存硬的,所以能抗 GPU;Bcrypt 不是,所以抗 GPU 能力一般。这个结论很多人记住了,但背后的原因往往说不清楚。理解这一点,能帮你在选择参数时知道该往哪个方向调。
显卡的优势来自并行
先看显卡为什么擅长破解哈希。
一张高端显卡有几千个计算核心,虽然单个核心的性能远不如 CPU 的一个核心,但胜在数量。哈希算法的每一次计算都是独立的——计算这个候选口令的结果,不影响下一个候选口令的计算。这种「互不依赖」的特性让显卡可以把成千上万个候选口令分摊到各个核心上同时计算。
所以显卡的破解速度可以达到 CPU 的成百上千倍。这也是为什么 MD5、SHA-256 这类纯计算型算法在显卡面前几乎没有抵抗力。
内存是并行度的瓶颈
现在考虑一个需要占用内存的算法。
假设每次计算需要占用 64 MiB 内存。显卡有 8 GiB 显存,那么同时能运行的实例数大约是 128 个——因为第 129 个实例没有内存可用了。哪怕显卡有五千个核心,也只有一百多个能派上用场,其余全部闲置。
这就是内存硬的核心机制:用内存需求限制并行度。
对于纯计算型算法,限制并行度的因素是核心数量,而核心数量可以通过买更好的硬件来提升。对于内存硬算法,限制并行度的是内存容量,而内存容量的提升速度远慢于计算能力的提升,而且成本高得多。
更关键的是,内存的需求是每个实例独立的。如果攻击者想同时试一万个口令,就需要一万份 64 MiB 的内存,也就是 640 GiB。这在成本上直接劝退了大部分攻击者。
为什么 ASIC 也受影响
有人会问:既然显卡受限,那专门造 ASIC 芯片是不是能绕过这个问题?
答案是影响仍在。ASIC 的优势是可以为特定算法定制电路,把计算单元做得极其高效。但内存是物理器件,它不能像逻辑门那样被无限压缩。芯片上要放多少内存,就必须占多大的硅片面积,成本随之上升。
所以对于内存硬算法,ASIC 攻击者同样面临「内存容量决定并行度」的约束。而 Bcrypt 这类只消耗 CPU 时间的算法,ASIC 可以堆叠大量计算单元,用很小的芯片面积获得极高的吞吐。
这就是为什么 Argon2 被设计成内存硬:它把攻击成本的瓶颈从「算力」转移到了「内存」,而内存是一种更难通过规模化来降低单位成本的资源。
参数怎么调才有意义
理解机制之后,参数调整的方向就清楚了。
m 是内存硬化的直接控制项。设得越大,攻击者需要的显存就越多,能并行的实例就越少。所以 m 是抵抗显卡的关键参数。
但要注意一个下限:m 低于 8 MiB 时基本失去内存硬化的意义。因为现代显卡的显存动辄几十 GB,几 MiB 的内存需求对它来说毫无压力,并行度完全不受限制。这样的配置虽然名义上用的是 Argon2,实际保护效果接近于一个普通的慢哈希。
反过来,t 只增加计算轮数,不改变内存需求。在总耗时预算固定的情况下,把预算分配给 m 比分配给 t 更有效——因为提高 m 同时增加了攻击者的内存压力和计算量,而提高 t 只增加计算量。
这解释了前面提到的原则:优先保证 m 足够大,再用 t 微调。如果服务器内存紧张,宁可降低 t 也要保住 m。
还有哪些算法是内存硬的
除了 Argon2,scrypt 也是内存硬算法,同样通过可调的内存参数来抵抗并行破解。它的设计早于 Argon2,在某些体系里仍有使用。
相比之下,PBKDF2 和 Bcrypt 都不消耗大量内存。PBKDF2 只是反复迭代 HMAC,Bcrypt 的内存占用是固定的一个小值。它们的保护来自「让每次计算变慢」,但慢的方式是消耗 CPU 时间,而 CPU 时间对显卡来说是可以并行摊薄的。
所以 OWASP 的推荐顺序是 Argon2id、scrypt、Bcrypt、PBKDF2——这个顺序大致对应着抗并行破解能力的强弱。
检查清单
- 显卡的优势来自大量核心并行计算互不依赖的任务
- 内存硬算法让每个计算实例占用大块内存,从而限制并行度
- 并行度受限意味着再多的核心也派不上用场,攻击成本上升
- ASIC 同样受内存容量的物理约束,硅片面积和成本无法规避
m是内存硬化的关键参数,低于 8 MiB 基本失去意义- 在耗时预算固定时,优先提高
m而不是t - scrypt 同为内存硬算法,PBKDF2 与 Bcrypt 不属于此类