【问题标题】:Hash function not returning the same output for identical input哈希函数不会为相同的输入返回相同的输出
【发布时间】:2018-12-17 01:43:09
【问题描述】:

我目前正在开发一个允许用户(虚构)买卖股票的网站。这是哈佛 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

打印语句打印的值是:

给定密码:q

给定哈希:

pbkdf2:sha256:50000$iAjKAPM1$f7644f34f21864062efa2f3e3f3ea0a89a8a3391a0223c1a62fa7cbaab012a71

实际哈希:

pbkdf2:sha256:50000$sBxqbmza$e35dd4e61eb186af014e5e1ce3b73450b1361baabdd2f5f4559ad83ef0d5b45b

对于很长的帖子表示歉意。有谁知道是什么导致哈希函数为(看似)相似的输入输出不同的哈希值?

谢谢!

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

NEW CODE

【问题讨论】:

  • 您的generate_password_hash 函数在哪里?在任何情况下,哈希都是加盐的——所以每次都会不同。
  • 我想一定是盐的问题。见generate_password_hash盐是由函数生成的。另请参阅 check_password_hash
  • 旁注:您不应该依赖 PBKDF2 的默认工作因子/迭代计数(即使 50K 也可以)。但是,是的,在盐和调用check 方法而不是手动进行比较的想法上(它不是借调的,所以......)。
  • 感谢您的 cmets!我想我已经解决了这个问题。 generate_password_hash 函数来自 werkzeug.security (check_password_hash, generate_password_hash)。它们包括一个 check_password_hash 函数,它成功了。我已将新代码复制到原始问题中。
  • 这不是一个好主意。您可以要求@kelalaka 发布答案,因为 kelalaka 已经将其放在评论中,或者您可以创建自己的答案。问题是为了问题,答案是为了答案。

标签: python html encryption hash sha256


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2012-01-18
    • 2019-10-30
    • 1970-01-01
    • 2016-08-17
    • 2014-11-30
    • 1970-01-01
    相关资源
    最近更新 更多