哈希函数不会为相同的输入返回相同的输出
Hash function not returning the same output for identical input
我目前正在开发一个允许用户(虚构地)买卖股票的网站。这是哈佛大学 CS50 计算机科学课程中的第 9 题。我的程序可以编译、运行并通过所有检查。但是,过去几天我一直在尝试实施密码更改选项。
在密码更改页面上,我提示用户输入旧密码。然后,用户必须输入他们想要的新密码。最后,用户必须再次确认他们的新密码。
但是,当用户输入他们的旧密码时,我的散列函数似乎输出了一个不同的散列值,而不是他们使用这个密码注册时输出的散列值。这导致我在数据库中的散列密码和用户输入之间的比较检查总是 return 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
但是,当我在 'original password' 表单字段中输入 'q' 时,generate_password__hash 函数 return 的哈希值:
pbkdf2:sha256:50000$iAjKAPM1$f7644f34f21864062efa2f3e3f3ea0a89a8a3391a0223c1a62fa7cbaab012a71
打印语句打印的值是:
给定密码:q
给定的哈希值:
pbkdf2:sha256:50000$iAjKAPM1$f7644f34f21864062efa2f3e3f3ea0a89a8a3391a0223c1a62fa7cbaab012a71
实际哈希:
pbkdf2:sha256:50000$sBxqbmza$e35dd4e61eb186af014e5e1ce3b73450b1361baabdd2f5f4559ad83ef0d5b45b
很抱歉post。有谁知道是什么导致哈希函数为(看似)相似的输入输出不同的哈希值?
谢谢!
编辑:这个新代码似乎解决了问题:
NEW CODE
正如本文所指出的 some libraries generate the salt itself, you don't supply one. In this library, you can only supply the salt size. From the doc
werkzeug.security.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 check_password_hash() can check the hash.
The format for the hashed string looks like this:
method$salt$hash
如果你想存储盐,从结果中解析它。但是这个库还有另一个功能 check/verify 密码;
werkzeug.security.check_password_hash(pwhash, password)
check a password against a given salted and hashed password value.
所以;
在注册登录,或更改密码使用;
generate_password_hash
要验证密码,请使用;
check_password_hash
我目前正在开发一个允许用户(虚构地)买卖股票的网站。这是哈佛大学 CS50 计算机科学课程中的第 9 题。我的程序可以编译、运行并通过所有检查。但是,过去几天我一直在尝试实施密码更改选项。
在密码更改页面上,我提示用户输入旧密码。然后,用户必须输入他们想要的新密码。最后,用户必须再次确认他们的新密码。
但是,当用户输入他们的旧密码时,我的散列函数似乎输出了一个不同的散列值,而不是他们使用这个密码注册时输出的散列值。这导致我在数据库中的散列密码和用户输入之间的比较检查总是 return 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
但是,当我在 'original password' 表单字段中输入 'q' 时,generate_password__hash 函数 return 的哈希值:
pbkdf2:sha256:50000$iAjKAPM1$f7644f34f21864062efa2f3e3f3ea0a89a8a3391a0223c1a62fa7cbaab012a71
打印语句打印的值是:
给定密码:q
给定的哈希值:
pbkdf2:sha256:50000$iAjKAPM1$f7644f34f21864062efa2f3e3f3ea0a89a8a3391a0223c1a62fa7cbaab012a71
实际哈希:
pbkdf2:sha256:50000$sBxqbmza$e35dd4e61eb186af014e5e1ce3b73450b1361baabdd2f5f4559ad83ef0d5b45b
很抱歉post。有谁知道是什么导致哈希函数为(看似)相似的输入输出不同的哈希值?
谢谢!
编辑:这个新代码似乎解决了问题:
NEW CODE
正如本文所指出的
werkzeug.security.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 check_password_hash() can check the hash.
The format for the hashed string looks like this:
method$salt$hash
如果你想存储盐,从结果中解析它。但是这个库还有另一个功能 check/verify 密码;
werkzeug.security.check_password_hash(pwhash, password)
check a password against a given salted and hashed password value.
所以;
在注册登录,或更改密码使用;
generate_password_hash
要验证密码,请使用;
check_password_hash