最佳加密工作因素是什么?


68

我正在使用Java scrypt库进行密码存储。当我加密事物时N,它需要一个rp值,其文档称为“ CPU成本”,“内存成本”和“并行化成本”参数。唯一的问题是,我实际上不知道它们的具体含义,或者对他们有什么好的价值。也许它们以某种方式对应于Colin Percival原始应用程序上的-t,-m和-M开关?

有人对此有任何建议吗?该库本身列出了N = 16384,r = 8和p = 1,但是我不知道这是强还是弱还是什么。


仅提示:如果密码存储数据可能被劫持(即,如果有备份),则不存储密码加密,而是存储与访问密钥连接的密码。这样可以防止字典攻击。
朱普·艾肯

我已经为该问题发布了通用答案,但是我当然会欢迎一些CPU时间和内存使用情况统计信息的更详细答案。
Maarten Bodewes 2012年

4
@JoopEggen不知道您想说什么
CodesInChaos

10
@乔普·艾根(Joop Eggen):。即使带有盐,SHA1也不是Key派生函数。 不要使用。另一方面,SCrypt是非常好的。足够高兴的是,OP意识到了基本问题。
gimpf 2012年

2
@JoopEggen在这篇文章中没有说明,但是scrypt + requires +一个明确的盐要作为参数(在N / r / p旁边)传递。而且,强烈建议您使用加密安全的PRNG提供的+ random +盐(我经常使用16或32字节盐)
Cerber 2012年

Answers:


70

首先:

cpercival在他2009年的幻灯片中提到一些

  • <100ms(互动使用)时(N = 2 ^ 14,r = 8,p = 1)
  • (N = 2 ^ 20,r = 8,p = 1)<5s(敏感存储)。

即使在今天(2012-09年),这些值也足以用于一般用途(某些WebApp的密码数据库)。当然,具体取决于应用程序。

同样,这些值(大部分)表示:

  • N:一般工作系数,迭代次数。
  • r:用于基础哈希的块大小;微调相对内存成本。
  • p:并行化因子;微调相对的cpu成本。

r并且p是为了适应潜在的问题,随着预期的CPU速度和内存大小和带宽不增加。如果CPU性能提高得更快,那么您p应该增加,而内存技术上的突破则应该提高一个数量级r。并且N可以跟上每隔一段时间性能的一般翻番。

重要:所有值都会改变结果。(更新:)这就是为什么所有scrypt参数都存储在结果字符串中的原因。


27
顺便说一句,scrypt参数自动存储在结果密钥中,因此它们不需要单独存储。这意味着随着时间的流逝,您可以为密码存储区中的用户密码中的参数设置不同的值,并且当用户更改其密码时,将使用当前参数值生成密钥(哈希密码)。
Kaitsu 2012年

2
感谢您指出了这一点; 我没有意识到链接的Java实现以理智的方式做到这一点。
gimpf 2012年

4
“顺便说一句,scrypt参数自动存储在结果密钥中,因此它们不需要单独存储。”-只是为了澄清(对于其他读者),这仅适用于Java实现。scrypt标准和其他实现不需要将成本/参数与结果哈希一起存储。
elithrar 2015年

1
只是为了澄清@elithrar的评论,Colin Percival本人(scrypt的作者)使用的格式将工作因素存储在生成的密钥中(详细信息在security.stackexchange.com/questions/88678#answer-91050上
ChrisV

3
@elithrar的scrypt论文没有详细说明格式(在定义4中建议,第11页),但是可以在代码中看到,或更有用的是在Colin的格式规范中(抱歉,回复太晚)。
克里斯夫

61

简短答案

这样一来,验证密码就需要250毫秒

长答案

scrypt运行所需的内存计算如下:

128字节N_cost××r_blockSizeFactor

对于参数你引用(N=16384r=8p=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参数视为一个矩形。哪里:

  • 宽度是所需的内存量(128 N r)
  • 高度是执行的迭代次数
  • 得到的面积就是整体硬度

在此处输入图片说明

  • costÑ)同时增加内存使用迭代
  • blockSizeFactor[R )增加的内存使用情况

其余参数parallelizationp)意味着您必须将整个操作进行2、3或多次:

在此处输入图片说明

如果您的内存比CPU多,则可以并行计算三个单独的路径-需要三倍的内存:

在此处输入图片说明

但是在所有实际的实现中,它都是按顺序计算的,是所需计算的三倍:

在此处输入图片说明

实际上,p除了之外,没有人选择其他因素p=1

理想因素是什么?

  • 尽可能多的RAM
  • 尽可能多的时间!

奖金表

上面的图形版本;您的目标是〜250ms:

在此处输入图片说明

笔记:

  • 垂直轴是对数刻度
  • 成本因素(水平)本身就是对数(迭代次数= 2 CostFactor
  • r=8曲线中突出显示

并将以上版本放大到合理区域,再次查看〜250ms幅度:

在此处输入图片说明

奖金Chat不休

  • 如果将scrypt配置为使用少于4 MB 1,则scrypt的密码存储能力比bcrypt弱 
  • 关于身份验证的密码哈希(即,验证时间<1,000毫秒),Argon2(i / d / id)比bcrypt弱 2

谢谢您的分析,它真的很有用。仅有一个问题:我目前正在使用Bouncy Castle实现在Android上进行测试-bouncycastle.org/docs/docs1.5on/org/bouncycastle/crypto/…,并且内存使用量正好高出2倍(128×N×r×2 )。知道为什么...吗?
Quark 2015年

2
@Tron我要猜测,因为有一点它会将内存复制到另一个缓冲区(即,将16MB传递给PBKDF2,后者执行实际的最终密钥派生)。
伊恩·博伊德

1
需要改进:虽然确实是影响大内存块周围的伪随机跳转次数的唯一因素,但计算成本仍然由N和r决定,因为存在4 * r Salsa20 / 8迭代N个迭代中的每个迭代(2 * r生成内存块,然后在内存块周围跳转时生成2 * r)。
尼克·鲍尔

请问为什么r = 1不超过2 ^ 14?
My1

但是这个答案真的很好,并且很好地解释了scrypt的知识。
My1

11

我不想采用上面提供的出色答案,但是没有人真正谈论“ r”为何具有其价值。Colin Percival的Scrypt论文提供的底层答案是,它与“内存延迟带宽积”有关。但这实际上意味着什么?

如果您正确执行Scrypt,则应该有一个大的内存块,该内存块主要位于主内存中。主内存需要花费一些时间。当块跳转循环的迭代首先从大块中选择一个元素以混合到工作缓冲区中时,它必须等待100 ns的量级才能到达第一块数据。然后,它必须请求另一个,并等待它到达。

对于r = 1,您将执行4nr Salsa20 / 8迭代2n延迟读取的主内存读取。

这不是很好,因为这意味着攻击者可以通过构建一个减少主内存延迟的系统来比您获得优势。

但是,如果您增加r并按比例减少N,则可以实现与以前相同的内存需求并进行相同数量的计算-除了您已将某些随机访问权换成顺序访问权之外。扩展顺序访问允许CPU或库有效地预取下一个所需的数据块。虽然初始等待时间仍然存在,但后来的块减少或消除的等待时间会将初始等待时间平均到最小水平。因此,与您相比,攻击者从改进其存储技术中不会获得任何收益。

但是,随着r的增加,收益递减,这与前面提到的“内存延迟带宽积”有关。该产品表明在任何给定时间可以从主存储器到处理器传输多少字节的数据。这与高速公路的想法相同-如果从A点到B点(延迟)需要10分钟的路程,并且道路从A点(带宽)到B点(带宽介于A点和B点之间)的速度为10分钟/分钟, B包含100辆汽车。因此,最佳r与您一次可以请求多少个64字节数据块有关,以掩盖该初始请求的延迟。

这样可以提高算法的速度,允许您根据需要增加N来增加内存和计算量,或者增加p来进行更多计算。

过多增加“ r”还有其他一些问题,我没有看到太多讨论:

  1. 增加r而减少N会减少内存周围伪随机跳转的次数。顺序访问更易于优化,并且可能为攻击者提供一个窗口。正如Colin Percival在Twitter上向我指出的那样,较大的r可能会使攻击者使用成本更低,速度更慢的存储技术,从而大大降低其成本(https://twitter.com/cperciva/status/661373931870228480)。
  2. 工作缓冲区的大小为1024r位,因此最终将被馈送到PBKDF2以产生Scrypt输出密钥的最终产品的数量为2 ^ 1024r。大内存块周围的跳转的排列(可能序列)数为2 ^ NlogN。这意味着内存跳跃循环有2 ^ NlogN个可能的乘积。如果1024r> NlogN,则似乎表明工作缓冲区混合不足。尽管我不确定这一点,并且希望看到一个证明或反证,但可能有可能在工作缓冲区的结果和跳转序列之间找到相关性,这可能使攻击者有机会减少其内存需求,而不会显着增加计算成本。再次,这是基于数字的观察-可能是每一轮中的所有东西都混合得很好,所以这不是问题。r = 8远低于标准N = 2 ^ 14的该潜在阈值-对于N = 2 ^ 14,此阈值将为r = 224。

总结所有建议:

  1. 选择r刚好足以平均化内存延迟对设备的影响,而没有其他影响。请记住,Colin Percival建议的值r = 8,在内存技术方面似乎仍然相当理想,而且显然在8年内并没有太大变化。16可能会稍微好一点。
  2. 确定每个线程要使用多少内存块,请记住这也会影响计算时间,并相应地设置N。
  3. 将p任意提高到您的用法可以容忍的水平(请注意:在我的系统上并使用自己的实现,p = 250(4个线程),N = 16384,r = 8需要大约5秒钟),并启用线程(如果可以处理)以及增加的内存成本。
  4. 调整时,建议使用较大的N和更大的存储块大小,以增加p和计算时间。Scrypt的主要优势来自其大的存储块大小。

我在带有i5-4300(2核,4线程)的Surface Pro 3上我自己实现Scrypt的基准,使用恒定的128Nr = 16 MB和p = 230;左轴是秒,下轴是r值,误差线是+/- 1标准偏差:

在恒定的大块大小的情况下加密r值与p


大桌子!看起来像有1个线程,N = 8192,r = 16,p = 1(已使用16MB内存),在您的系统和实现中,每次身份验证尝试的时间成本约为40ms。这是一个非常不错的成本。N = 16834,r = 8,p = 1只是稍微慢一点,但是看起来确实对较大的r有一点点但一致的优势。
CBHacking '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.