哈希函数对于相同的输入不返回相同的输出

时间:2018-12-16 15:55:41

标签: python html encryption hash sha256

我目前正在建立一个网站,该网站允许用户(虚构地)买卖股票。这是哈佛大学CS50计算机科学课程中的问题9。我的程序编译,运行并通过所有检查。但是,过去几天我一直在尝试实施密码更改选项。

在密码更改页面上,提示用户输入旧密码。然后,用户必须输入他们想要的新密码。最后,用户必须再次确认其新密码。

但是,当用户输入旧密码时,我的哈希函数似乎会输出与使用此密码注册时不同的哈希值。这导致我在数据库中的哈希密码和用户输入之间进行比较检查时始终返回false。

以下是用于执行密码更改的python代码。下面是实际页面的html代码,用户可以在该页面上更改密码。

@app.route("/change", methods=["GET", "POST"])
@login_required
# PERSONAL TOUCH: <Allows user to change their password>
def change():
"""Allows user to change their password"""

if request.method == "GET":
    return render_template("change.html")

else:

    # Returns an error if Password is left blank
    if not request.form.get("originalpassword"):
        return apology("User must submit their original Password.", 400)

    elif not request.form.get("newpassword"):
        return apology("User must submit a new Password.", 400)

    elif not request.form.get("newconfirmation"):
        return apology("User must confirm their new Password", 400)

    # Hashes the Password
    Password = request.form.get("originalpassword")
    print("GIVEN PASSWORD: ", Password)
    HashedPassword = generate_password_hash(Password, method='pbkdf2:sha256', salt_length=8)

    # Returns an error if the user typed in a non-valid original password
    OldHashedPassword = db.execute("SELECT hash FROM users WHERE id = :id", id=session["user_id"])
    Old_HPW = OldHashedPassword[0]["hash"]

    print("given hash: ", HashedPassword)
    print("actual hash: ", Old_HPW)

    print("=====\n",OldHashedPassword,"\n=====\n")

    if not Old_HPW == HashedPassword:
        return apology("Submitted password is not valid.")

    # Returns an error if Password and Confirmation are not identical
    if not request.form.get("newpassword") == request.form.get("confirmpassword"):
        return apology("New Password and Confirmation must be identical.", 400)

    # Hashes the new Password
    NewPassword = request.form.get("newpassword")
    NewHashedPassword = generate_password_hash(NewPassword, method='pbkdf2:sha256', salt_length=8)

    # Insert the new Password into the database
    insertPW = db.execute("INSERT INTO users (hash) VALUES(:hash)", hash=NewHashedPassword)

    return redirect("/")

以及HTML代码:

HTML Code

为了调试,我确实包含了一些打印语句。我用用户名“ q”和密码“ q”注册了一个新帐户。然后,我尝试将密码更改为“ qq”。注册期间,输入“ q”导致以下哈希:

pbkdf2:sha256:50000 $ sBxqbmza $ e35dd4e61eb186af014e5e1ce3b73450b1361baabdd2f5f4559ad83ef0d5b45b

但是,当我在“原始密码”表单字段中输入“ q”时,generate_password__hash函数将返回哈希值:

pbkdf2:sha256:50000 $ iAjKAPM1 $ f7644f34f21864062efa2f3e3f3ea0a89a8a3391a0223c1a62fa7cbaab012a71

print语句打印的值是:

给定密码:q

给定的哈希:

pbkdf2:sha256:50000 $ iAjKAPM1 $ f7644f34f21864062efa2f3e3f3ea0a89a8a3391a0223c1a62fa7cbaab012a71

实际哈希:

pbkdf2:sha256:50000 $ sBxqbmza $ e35dd4e61eb186af014e5e1ce3b73450b1361baabdd2f5f4559ad83ef0d5b45b

很长的帖子很抱歉。有人知道是什么导致哈希函数为(看似)相似的输入输出不同的哈希值吗?

谢谢!

编辑:这段新代码似乎已经解决了问题:

NEW CODE

1 个答案:

答案 0 :(得分:1)

正如本answer中指出的那样,有些库本身会生成盐,而您不会提供它。在此库中,您只能提供盐量。从doc

werkzeug.security.generate_password_hash(password, method='pbkdf2:sha256', salt_length=8)
  

使用给定的方法散列密码,并使用给定长度的字符串散列盐。返回的字符串格式包括所使用的方法,以便check_password_hash()可以检查哈希。

     

哈希字符串的格式如下:

method$salt$hash

如果要存储盐,请从结果中进行解析。但是该库还有另一个功能,可以检查/验证密码;

werkzeug.security.check_password_hash(pwhash, password)
  

根据给定的加密哈希值和密码值检查密码。

所以;

在注册登录或更改密码时使用;

generate_password_hash

要验证密码,请使用;

check_password_hash