-1

我有两个休息端点,一个注册用户,第二个让该用户登录。这是我用来散列用户密码并将散列后的密码存储在数据库中的代码,

from passlib.hash import pbkdf2_sha256
def _get_hashed_password(self, password):
    return pbkdf2_sha256.encrypt(password, rounds=200000, salt_size=16)

现在在登录端点上,我使用此代码验证散列密码,

password = data['password']
hash = pbkdf2_sha256.encrypt(password, rounds=200000, salt_size=16)
pbkdf2_sha256.verify(user.hashed_password, hash)

这个方法失败了,很明显是因为两个密码不同,

$pbkdf2-sha256$200000$ai0FoDTG2BuDkDKGEIJQKg$Ik06dr61.2rRMDwZCZMdVq.zMe5887.ksDxvmSXFRwE
$pbkdf2-sha256$200000$pHTuHYNwLoXQeu8dI0QoxQ$2z4cZl9Njz9X/bxNtWCZzzeplWO.jTZA2v5lvcmgFE8

我想知道我怎样才能让它工作?

4

1 回答 1

6

pbkdf2_sha256.encryptpbkdf2_sha256.verify的不仅仅是计算密码的哈希值。仔细看输出pbkdf2_sha256.encrypt

$pbkdf2-sha256$200000$ai0FoDTG2BuDkDKGEIJQKg$Ik06dr61.2rRMDwZCZMdVq.zMe5887.ksDxvmSXFRwE
----------------------------------------------------------------------------------------
$  algorithm  $rounds$         salt         $             the actual hash

您可以切换算法,在几年内增加轮数,并且pbkdf2_sha256.verify仍然能够根据存储在数据库中的哈希验证明文密码。

两次散列相同的密码不会每次都给您相同的结果,因为使用了随机盐。如果攻击者可以访问您的密码哈希,盐可以防止彩虹表攻击。基本上,您不只是计算 ,而是hash(password)计算类似 的东西hash(salt + password)。由于上面的字符串中已经给出了盐,并且您大概知道密码,因此您也将知道的价值salt + password并且您的生活不会变得更加困难。但是对于只花费大量时间进行预计算的攻击者来说hash(password),这些哈希都没有用,因为它们没有包含您的随机盐。

正如评论中发布的示例一样,您无需执行任何特殊操作来验证您的密码:

pbkdf2_sha256.verify(password, user.hashed_password)

pbkdf2_sha256.encrypt验证密码时无需调用。pbkdf2_sha256.verify为您完成所有这些。

于 2018-01-07T05:46:03.280 回答