我如何利用werkzeug.security的check_password_hash函数针对现有的咸化sha1密码哈希验证正确的密码

问题描述 投票:1回答:1

我正在开发一个新的python应用程序,该应用程序需要验证我们数据库中现有的用户凭据。我们的许多遗留应用程序都建立在PHP的Symfony框架上,而这些密码散列和盐本来就是该框架的来源。在数据库中,将保留用户的算法(sha1),salt和哈希密码。我试图弄清楚如何结合使用check_password_hash模块的werkzeug.security功能使用此信息正确验证密码。但是,到目前为止,我一直没有成功。

出于演示目的,我创建了一个测试用户,并且数据库包含该用户的以下值。

测试用户值

algorithm:sha1salt:e40e1e9addc186828a5554a71527342cpassword(哈希):784517f57fbe61179960739e29d7ae925aa4fd5b

测试用户的实际密码为123456

我尝试了以下方法来验证密码。

注意:1.哈希格式改编自werkzeug.security文档2.比较哈希方法改编自this StackOverflow answer

from werkzeug.security import generate_password_hash
from werkzeug.security import check_password_hash

# Attempt 1 - Results in False
check_password_hash('sha1$e40e1e9addc186828a5554a71527342c$784517f57fbe61179960739e29d7ae925aa4fd5b','123456')

# Attempt 2 - Results in False
check_password_hash('pbkdf2:sha1$e40e1e9addc186828a5554a71527342c$784517f57fbe61179960739e29d7ae925aa4fd5b','123456')

# Attempt 3
# Step 1: Append the salt_value to the given password and hash it using the same hash function.
generate_password_hash('123456$e40e1e9addc186828a5554a71527342c','sha1')
# sha1$9lUceSsd$60f7dcb3ff9c22d4613e59fcbfed0c463ee4189e
# Step 2: Compare the hash to the hash in the database
# 60f7dcb3ff9c22d4613e59fcbfed0c463ee4189e != 784517f57fbe61179960739e29d7ae925aa4fd5b

# Attempt 4 - Same steps as Attempt 3 except adding salt_length argument
# Step 1: Append the salt_value to the given password and hash it using the same hash function.  
generate_password_hash('123456$e40e1e9addc186828a5554a71527342c','sha1',len('e40e1e9addc186828a5554a71527342c'))
# sha1$EbPv6DP0wMyu02UpA6ZYazFvvYvZTVI1$b8252583fea027d42af20c0d0f3eac3fbf468bd1
# Step 2: Compare the hash to the hash in the database
# b8252583fea027d42af20c0d0f3eac3fbf468bd1 != 784517f57fbe61179960739e29d7ae925aa4fd5b

任何人都可以对我做错的事情提供一些见解吗?我应该尝试使用passlib这样的其他库吗?我希望这个模块能够满足我的需求,因为我已经创建了一些现有的python应用程序,将其用于new用户注册,但是在单独的数据库中。

python python-3.x flask werkzeug
1个回答
0
投票

werkzeug.generate_password_hash要生成一个盐值。看一下源代码,我们可以看到_hash_internal被生成的盐值调用。

def generate_password_hash(password, method="pbkdf2:sha256", salt_length=8):
    """Hash a password with the given method and salt with a string of
    the given length. The format of the string returned includes the method
    that was used so that :func:`check_password_hash` can check the hash.

    The format for the hashed string looks like this::

        method$salt$hash

    This method can **not** generate unsalted passwords but it is possible
    to set param method='plain' in order to enforce plaintext passwords.
    If a salt is used, hmac is used internally to salt the password.

    If PBKDF2 is wanted it can be enabled by setting the method to
    ``pbkdf2:method:iterations`` where iterations is optional::

        pbkdf2:sha256:80000$salt$hash
        pbkdf2:sha256$salt$hash

    :param password: the password to hash.
    :param method: the hash method to use (one that hashlib supports). Can
                   optionally be in the format ``pbkdf2:<method>[:iterations]``
                   to enable PBKDF2.
    :param salt_length: the length of the salt in letters.
    """
    salt = gen_salt(salt_length) if method != "plain" else ""
    h, actual_method = _hash_internal(method, salt, password)
    return "%s$%s$%s" % (actual_method, salt, h)

如果我们使用您的_hash_internal方法调用sha1,并提供了salt /密码,则会得到不同的哈希值

In [83]: import werkzeug.security                                                                                                                                                     

In [84]: h, method = werkzeug.security._hash_internal('sha1', 'e40e1e9addc186828a5554a71527342c', '123456')                                                                           

In [86]: h == '784517f57fbe61179960739e29d7ae925aa4fd5b'                                                                                                                              
Out[86]: False

In [85]: h                                                                                                                                                                            
Out[85]: 'e8c2de9bdc1ab92479e3e55b608a040dad7bf656'

我认为您需要重新访问PHP代码以查看如何生成这些值。

© www.soinside.com 2019 - 2024. All rights reserved.