对于大多数面向公众的服务,您通常可以在用户开始生气之前登录超过250毫秒到400毫秒。
如果我们认为对于登录尝试有一次数据库调用,那么登录/注册中rounds
的最佳价值是什么?它使用 MongoDB 和非阻塞调用。 (使用Mongotor,并将电子邮件用作_id
,因此默认情况下已编入索引,查询速度很快: 0.00299978256226 当然使用 3条记录 ...)
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
对生产有益的时候,你能给我一个很好的回合价值吗?
答案 0 :(得分:17)
(这里是passlib开发者)
pbkdf2_sha512所花费的时间与它的轮次参数(elapsed_time = rounds * native_speed
)成线性比例。使用系统数据native_speed = 12000 / .143 = 83916 iterations/second
,这意味着您需要大约83916 * .350 = 29575 rounds
才能获得~350ms的延迟。
对于bcrypt来说,事情有点小问题,因为它花费的时间与它的轮次参数(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)
(编辑:添加了关于安全最小轮次的回复......)
免责声明:确定一个安全的最小值是一个令人惊讶的棘手问题 - 有许多难以量化的参数,很少的真实世界数据,以及一些严格无益的理论。由于缺乏良好的权威,我自己一直在研究这个话题;为了进行袖口计算,我将原始数据简化为一个简短的公式(下图),这通常是我使用的。请注意,背后是几页假设和粗略估计,使其更像Fermi Estimation而不是确切答案:|
我使用GPU攻击PBKDF2-HMAC-SHA512的经验法则(2012年中)是:
days * dollars = 2**(n-31) * rounds
days
是攻击者有50/50机会猜测密码的天数。dollars
是攻击者&#39;硬件预算(以美元计)。n
是用户密码中的平均熵数(以位为单位)。 要回答你的脚本小子问题:如果一般密码有32位熵,而且攻击者有一个2000美元的系统和一个好的GPU,那么在30000回合他们将需要30天( 2**(32-31)*30000/2000
)有50/50的机会破解给定的哈希值。我建议您玩这些价值观,直到您达到您认为适合的轮次/天权衡。
要记住的一些事情:
字典攻击的成功率不是线性的,它更像是长尾&#34;情况,所以把50/50标记看作更多的半衰期。
31
是关键因素,因为它编码了使用特定技术级别攻击特定算法的成本估算。实际值2**-31
衡量每轮&#34;美元天数&#34;这将花费一个攻击者。为了比较,使用ASIC攻击PBKDF2-HMAC-SHA512的因子更接近46
- 更大的数字意味着攻击者的降压更多,而且每轮的安全性更低,虽然脚本小子一般不会有这样的预算:)