1)盐是随机的,使用os.urandom
. 因此,我想知道该verify
方法是否能够以某种方式从哈希中提取盐?
该hash
方法返回一个对盐、参数和密码哈希本身进行编码的字符串,如文档中所示:
>>> from argon2 import PasswordHasher
>>> ph = PasswordHasher()
>>> hash = ph.hash("s3kr3tp4ssw0rd")
>>> hash
'$argon2id$v=19$m=102400,t=2,p=8$tSm+JOWigOgPZx/g44K5fQ$WDyus6py50bVFIPkjA28lQ'
>>> ph.verify(hash, "s3kr3tp4ssw0rd")
True
该格式在 Argon2 参考实现中进行了总结;也许还有其他参考资料。在这种情况下:
$argon2id$...
哈希是 Argon2id,这是每个人都应该使用的特定 Argon2 变体(结合了 Argon2i 的侧通道阻力和更难破解的 Argon2d)。
...$v=19$...
哈希的版本是 0x13(十进制的 19),意思是 Argon2 v1.3,密码哈希竞赛采用的版本。
...$m=102400,t=2,p=8$...
内存使用为 100 MB (102400 KB),时间为 2 次迭代,并行度为 8 路。
...$tSm+JOWigOgPZx/g44K5fQ$...
盐是tSm+JOWigOgPZx/g44K5fQ
(base64)或b5 29 be 24 e5 a2 80 e8 0f 67 1f e0 e3 82 b9 7d
(十六进制)。
...$WDyus6py50bVFIPkjA28lQ
密码哈希本身是WDyus6py50bVFIPkjA28lQ
(base64)或58 3c ae b3 aa 72 e7 46 d5 14 83 e4 8c 0d bc 95
(十六进制)。
该verify
方法采用此字符串和候选密码,使用所有编码参数重新计算密码哈希,并将其与编码密码哈希进行比较。
如果 Argon2 确实可以从哈希中提取盐,那么在这种情况下使用盐如何更安全,因为获得哈希密码的敌对实体也应该能够提取盐?
salt 的目的是通过简单地对每个用户进行不同的处理来减轻多目标攻击的批量优势。
在 32 字节字符串中随机均匀地选择盐只是保证每个用户都有不同的盐的简单方法。原则上,可以想象一个权威机构向世界上的每个人分发一个连续的数字作为他们的 Argon2 盐,但该系统不能很好地扩展——我的意思不仅仅是你的应用程序可以使用计数权威,而是世界上的每个应用程序都必须使用相同的计数权限,我认为芝麻街的计数太忙了,无法承担这项工作。
2)默认情况下,我不向该hash
方法提供任何秘密,而是密码本身似乎被用作秘密。这安全吗?我不提供散列方法的秘密有什么缺点?
一般来说,密码就是秘密:如果有人知道密码,那么他们应该能够登录;如果他们不知道密码,他们应该被带到门口!
也就是说,Argon2还支持密钥,它与盐分开,与密码分开。
如果您的密码数据库和您的应用程序之间存在有意义的安全边界,因此攻击者可能会破坏其中一个而不是另一个,那么应用程序可以选择一个统一的随机 32 字节字符串作为密钥,并将其与 Argon2 一起使用使得密码哈希是秘密密码的秘密函数。
这样,转储密码数据库但没有转储应用程序密钥的对手甚至无法测试密码的猜测,因为他们不知道计算密码哈希所需的密钥。