我正在使用Java scrypt 库来存储密码。当我加密事物时,它需要一个N
,r
和p
值,它的文档将其称为“CPU成本”、“内存成本”和“并行化成本”参数。唯一的问题是,我实际上并不知道它们的具体含义,或者对它们有什么好的价值;也许它们以某种方式对应于Colin Percival 原始应用程序上的 -t、-m 和 -M 开关?
有人对此有什么建议吗?该库本身列出了 N = 16384,r = 8 和 p = 1,但我不知道这是强还是弱或什么。
我正在使用Java scrypt 库来存储密码。当我加密事物时,它需要一个N
,r
和p
值,它的文档将其称为“CPU成本”、“内存成本”和“并行化成本”参数。唯一的问题是,我实际上并不知道它们的具体含义,或者对它们有什么好的价值;也许它们以某种方式对应于Colin Percival 原始应用程序上的 -t、-m 和 -M 开关?
有人对此有什么建议吗?该库本身列出了 N = 16384,r = 8 和 p = 1,但我不知道这是强还是弱或什么。
作为开始:
cpercival在他 2009 年的幻灯片中提到了一些东西
即使在今天(2012-09),这些值对于一般用途(某些 WebApp 的密码数据库)也足够好。当然,具体取决于应用程序。
此外,这些值(大部分)意味着:
N
:一般工作因子,迭代次数。r
: 用于底层哈希的块大小;微调相对内存成本。p
: 并行化因子;微调相对 CPU 成本。r
并且p
旨在解决 CPU 速度、内存大小和带宽未按预期增加的潜在问题。如果 CPU 性能提高得更快,你就会提高p
,相反,如果内存技术的突破提供一个数量级的改进,你就会提高r
。并且N
是否可以跟上每个时间跨度的一般性能翻倍。
重要提示:所有值都会改变结果。(更新:)这就是为什么所有 scrypt 参数都存储在结果字符串中的原因。
这样验证密码需要 250 毫秒
scrypt 运行所需的内存计算如下:
128 字节 × cost (N)×blockSizeFactor (r)
对于您引用的参数 ( N=16384
, r=8
, p=1
)
128×16384×8 = 16,777,216 字节 = 16 MB
选择参数时必须考虑到这一点。
Bcrypt比 Scrypt “弱”(尽管仍然比 PBKDF2 强三个数量级),因为它只需要 4 KB 的内存。你想让硬件中的并行破解变得困难。例如,如果显卡有 1.5 GB 的板载内存,并且您将 scrypt 调整为消耗 1 GB 内存:
128×16384×512 = 1,073,741,824 字节 = 1 GB
然后攻击者无法在他们的视频卡上并行化它。但是,您的应用程序/电话/服务器每次计算密码时都需要使用 1 GB 的 RAM。
它可以帮助我将 scrypt 参数视为一个矩形。在哪里:
cost
( N ) 增加了内存使用和迭代。blockSizeFactor
)增加内存使用量。剩余的参数parallelization
( p ) 意味着您必须执行整个操作 2、3 或更多次:
如果您的内存比 CPU 多,则可以并行计算三个单独的路径 - 需要三倍的内存:
但在所有现实世界的实现中,它是按顺序计算的,所需的计算量增加了三倍:
实际上,没有人选择过p
除 以外的因素p=1
。
理想的因素是什么?
以上的图形版本;你的目标是~250ms:
笔记:
r=8
曲线中突出显示并将上述版本放大到合理区域,再次查看~250ms 幅度:
我不想踩到上面提供的出色答案,但没有人真正谈论为什么“r”具有它所具有的价值。Colin Percival 的 Scrypt 论文提供的低级答案是它与“内存延迟-带宽乘积”有关。但这实际上意味着什么?
如果您正确使用 Scrypt,则应该有一个大内存块,该内存块主要位于主内存中。主内存需要时间来提取。当块跳跃循环的迭代首先从大块中选择一个元素以混合到工作缓冲区中时,它必须等待大约 100 ns 的时间才能让第一个数据块到达。然后它必须请求另一个,并等待它到达。
对于 r = 1,您将执行 4nr Salsa20/8 迭代和2n 延迟从主内存读取。
这不好,因为这意味着攻击者可以通过构建一个对主内存的延迟减少的系统来获得优势。
但是,如果您增加 r 并按比例减少 N,您就能够实现与以前相同的内存需求并执行相同数量的计算——除了您已经将一些随机访问换成了顺序访问。扩展顺序访问允许 CPU 或库有效地预取下一个所需的数据块。虽然初始延迟仍然存在,但后期块的减少或消除延迟将初始延迟平均到最低水平。因此,攻击者从改进他们的内存技术中获益甚微。
但是,随着 r 的增加,存在一个收益递减点,这与前面提到的“内存延迟-带宽乘积”有关。该产品表示的是在任何给定时间可以从主存储器传输到处理器的数据字节数。这与高速公路的想法相同——如果从 A 点行驶到 B 点需要 10 分钟(延迟),而道路从 A 点(带宽)以 10 辆/分钟的速度运送到 B 点,则 A 点和 B 点之间的道路B 包含 100 辆汽车。因此,最佳 r 与您一次可以请求多少个 64 字节数据块有关,以掩盖初始请求的延迟。
这提高了算法的速度,允许您根据需要增加 N 以获得更多内存和计算,或者增加 p 以获得更多计算。
增加“r”太多还有其他一些问题,我没有看到太多讨论:
总结所有建议:
我自己在具有 i5-4300(2 核,4 线程)的 Surface Pro 3 上实现 Scrypt 的基准,使用常数 128Nr = 16 MB 和 p = 230;左轴是秒,下轴是 r 值,误差线是 +/- 1 标准偏差: