8

来自passlib 文档

对于大多数面向公众的服务,在用户开始生气之前,您通常可以让登录时间超过 250 毫秒 - 400 毫秒。

那么,如果我们认为登录尝试对数据库有一个调用,并且它使用带有非阻塞调用的MongoDB ,那么登录/注册rounds的最佳价值是什么。(使用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

现在如果我使用半值:

password = hashh.encrypt("test", salt_size = 32, rounds = 4000) # returns 0.0720000267029
hashh.verify("test", password) # returns 0.0709998607635

我在戴尔 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

半值:

password = hashh.encrypt("test", rounds = 12) # 0.00699996948242 wonderful?
hashh.verify("test", password) # 0.00600004196167

你能建议我在使用时pbkdf2_sha512对生产有好处吗?

4

1 回答 1

22

(此处为 passlib 开发人员)

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

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


所有这些都是我希望在 passlib 的未来版本中解决的问题。作为一项正在进行的工作,passlib 的 mercurial repo 当前包含一个简单的小脚本,choose_rounds.py,它负责为给定的目标时间选择正确的轮数值。可以直接下载运行如下(运行可能需要20s左右):

$ 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)

(编辑:添加了关于安全最小轮次的响应......)

免责声明:确定一个安全的最小值是一个非常棘手的问题——有许多难以量化的参数、非常少的真实世界数据以及一些严格无益的理论。由于缺乏良好的权威性,我一直在自己研究这个话题;对于即兴计算,我将原始数据归结为一个简短的公式(如下),这通常是我使用的。请注意,它背后是几页假设和粗略估计,使其更像是费米估计而不是确切答案:|

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

 days * dollars = 2**(n-31) * rounds
  • 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- 更大的数字意味着攻击者的成本更高,并且每轮的安全性更低,尽管脚本小子通常不会有那种预算: )

于 2012-11-26T20:03:06.457 回答