Django升级未加盐的MD5密码不匹配

时间:2019-12-12 13:19:50

标签: django passwords

我正在迁移使用未加盐的MD5密码(恐怖!)的旧系统。

在用户登录时,我通过在PASSWORD_HASHERS的{​​{1}}列表中添加其他哈希来了解Django handles automatically password upgrading

但是,我想升级密码而不要求用户登录also explained in the docs

因此,我遵循了文档中的示例并实现了自定义哈希器settings.py

legacy/hasher.py

并将其添加到import secrets from django.contrib.auth.hashers import PBKDF2PasswordHasher, UnsaltedMD5PasswordHasher class PBKDF2WrappedMD5PasswordHasher(PBKDF2PasswordHasher): algorithm = "pbkdf2_wrapped_md5" def encode_md5_hash(self, md5_hash): salt = secrets.token_hex(16) return super().encode(md5_hash, salt) def encode(self, password, salt, iterations=None): md5_hash = UnsaltedMD5PasswordHasher().encode(password, salt="") return self.encode_md5_hash(md5_hash)

settings.py

但是,在Django shell PASSWORD_HASHERS = [ "django.contrib.auth.hashers.PBKDF2PasswordHasher", "legacy.hashers.PBKDF2WrappedMD5PasswordHasher", ] 中对其进行测试会为升级后的密码返回False。

check_password

我已经研究了other similar个问题,但在那里也没有找到合适的解决方案。

1 个答案:

答案 0 :(得分:2)

简短答案:在验证Django无法(可能)提供相同的编码密码时,不考虑提供的salt

发生这种情况的原因是因为您凭空产生“盐”,而忽略了所传递的salt。确实,如果我们看看您的实施情况,就会发现:

class PBKDF2WrappedMD5PasswordHasher(PBKDF2PasswordHasher):
    algorithm = "pbkdf2_wrapped_md5"

    def encode_md5_hash(self, md5_hash):
        salt = secrets.token_hex(16)  # generating random salt
        return super().encode(md5_hash, salt)

    def encode(self, password, salt, iterations=None):
        md5_hash = UnsaltedMD5PasswordHasher().encode(password, salt='')
        return self.encode_md5_hash(md5_hash)

因此,将忽略传递给salt方法的encode(..)

这意味着,如果您以后想要验证密码,Django将使用存储的encode(..)调用salt(在您的情况下,这是第二部分)密码,所以f3aae83b02e8727a2477644eb0aa6560),但是您决定扔掉它,并生成带有不同盐的密码,因此,编码密码不再与您存储在数据库中的密码匹配。 / p>

我建议使用盐,例如:

class PBKDF2WrappedMD5PasswordHasher(PBKDF2PasswordHasher):
    algorithm = "pbkdf2_wrapped_md5"

    def encode_md5_hash(self, md5_hash, salt):
        return super().encode(md5_hash, salt)

    def encode(self, password, salt, iterations=None):
        md5_hash = UnsaltedMD5PasswordHasher().encode(password, salt='')
        return self.encode_md5_hash(md5_hash, salt)