python passlib:"rounds"的最佳价值是什么

Abd*_* Pp 7 python encryption pbkdf2

来自passlib文档

对于大多数面向公众的服务,您通常可以在用户开始恼火之前注册250ms - 400ms.

那么,如果我们认为对于登录尝试有一次数据库调用,它rounds登录/注册中的最佳价值是什么,并且它使用MongoDB进行非阻塞调用.(使用Mongotor,并使用电子邮件作为,因此它默认索引,查询很快:0.00299978256226,当然使用具有3条记录的数据库测试...)_id

import passlib.hash
import time

hashh = passlib.hash.pbkdf2_sha512
beg1 = time.time()
password = hashh.encrypt("test", salt_size = 32, rounds = 12000)
print time.time()- beg1 # returns 0.142999887466
beg2 = time.time()
hashh.verify("test", password) # returns 0.143000125885
print time.time()- beg2
Run Code Online (Sandbox Code Playgroud)

现在,如果我使用半值:

password = hashh.encrypt("test", salt_size = 32, rounds = 4000) # returns 0.0720000267029
hashh.verify("test", password) # returns 0.0709998607635
Run Code Online (Sandbox Code Playgroud)

在戴尔XPS 15 i7 2.0 Ghz上使用Windows 7 64位

注意:安装了bcrypt,当然,直接使用它作为默认值是真的很痛苦(rounds = 12):

hashh = passlib.hash.bcrypt
beg1 = time.time()
password = hashh.encrypt("test", rounds = 12) # returns 0.406000137329
print time.time()- beg1
beg2 = time.time()
hashh.verify("test", password) # returns 0.40499997139
print time.time()- beg2
Run Code Online (Sandbox Code Playgroud)

半价值:

password = hashh.encrypt("test", rounds = 12) # 0.00699996948242 wonderful?
hashh.verify("test", password) # 0.00600004196167
Run Code Online (Sandbox Code Playgroud)

你能否建议我在使用时有良好的回合价值pbkdf2_sha512

Eli*_*ins 19

(passlib开发者在这里)

pbkdf2_sha512所花费的时间与它的rounds参数(elapsed_time = rounds * native_speed)成线性比例.使用系统的数据native_speed = 12000 / .143 = 83916 iterations/second,这意味着您需要大约83916 * .350 = 29575 rounds延迟~350ms.

事情对于bcrypt来说有点小问题,因为它花费的时间量与它的rounds参数(elapsed_time = (2 ** rounds) * native_speed)成对数比例.使用系统的数据native_speed = (2 ** 12) / .405 = 10113 iterations/second,这意味着您需要大约log(10113 * .350, 2) = 11.79 rounds延迟~350毫秒.但由于BCrypt只接受整数轮次参数,所以你需要选择rounds=11(~200ms)或rounds=12(~400ms).


所有这些都是我希望在将来发布的passlib中修复的内容.作为一项正在进行的工作,passlib的mercurial repo目前包含一个简单的小脚本choose_rounds.py,它负责为给定的目标时间选择正确的舍入值.您可以按如下方式直接下载并运行它(运行可能需要20秒左右):

$ python choose_rounds.py -h
usage: python choose_rounds.py <hash_name> [<target_in_milliseconds>]

$ python choose_rounds.py pbkdf2_sha512 350
hash............: pbkdf2_sha512
speed...........: 83916 iterations/second
target time.....: 350 ms
target rounds...: 29575  

$ python choose_rounds.py bcrypt 350
hash............: bcrypt
speed...........: 10113 iterations/second
target time.....: 350 ms
target rounds...: 11 (200ms -- 150ms faster than requested)
target rounds...: 12 (400ms -- 50ms slower than requested)
Run Code Online (Sandbox Code Playgroud)

(编辑:增加了关于安全最小轮数的回复...)

免责声明:确定一个安全的最小值是一个令人惊讶的棘手问题 - 有许多难以量化的参数,很少的真实世界数据,以及一些严格无益的理论.由于缺乏良好的权威,我一直在研究这个话题; 对于袖口计算,我把原始数据简化为一个简短的公式(下面),这通常是我使用的.请注意,背后是几页假设和粗略估计,使其更像是费米估计而不是一个确切的答案:

我使用GPU攻击PBKDF2-HMAC-SHA512的经验法则(2012年中)是:

 days * dollars = 2**(n-31) * rounds
Run Code Online (Sandbox Code Playgroud)
  • days 是攻击者有50/50机会猜测密码的天数.
  • dollars 是攻击者的硬件预算(以美元计).
  • n 是用户密码中的平均熵数(以位为单位).

回答你的脚本小子问题:如果一个平均密码有32位熵,并且攻击者有一个2000美元的系统和一个好的GPU,那么在30000回合他们需要30天(2**(32-31)*30000/2000)才有50/50的机会破解一个给定的哈希.我建议你玩这些价值观,直到你达成一个令你满意的轮数/天的权衡.

要注意的一些事项:

  • 字典攻击的成功率不是线性的,更多的是"长尾"情况,所以将50/50标记视为更多的半衰期.

  • 31是关键因素,因为它编码使用特定技术级别攻击特定算法的成本估算.实际值,2**-31测量"每轮美元天数"将使攻击者付出代价.相比之下,使用ASIC攻击PBKDF2-HMAC-SHA512 有一个因素更接近46- 更大的数字意味着攻击者的降压更多,而且每轮的安全性更低,尽管脚本小子一般不会有这样的预算: )

  • 很高兴它很有用!re:安全最小 - 我试图将我的回复编辑到500个字符,但放弃并将其作为我上面答案的附录添加 - 我希望它不会太长.它本质上是我计划添加到passlib手册(最终)的一些文本的清理版本. (2认同)