当我检查密码时,bcrypt 中的盐无效

Invalit salt in bcrypt when i checkpw

使用烧瓶 python。 当我尝试比较用 bcrypt.hashpw() 加密的散列密码时 说无效盐。

现在我测试它,如果我把这个 if 语句 wok 但只有在 html 表单的密码字段中我粘贴密码散列(问题是我需要输入普通密码) 所以比较我确定 html 中的表单字段并且连接到数据库以获取用户密码仅在我需要输入 bcrypt.checkpw(password_in_the_login_form.html, password_hashed_in_the_db 时失败) 每次都说 Invalid Salt,这里是我的代码:

app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = '01b0cfa6c076da9264d7ea8b44967445'
app.config['MYSQL_DB'] = 'flaskdb'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'
mysql = MySQL(app)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        email = request.form['Email']
        password = request.form['Password']

        curl = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
        curl.execute("SELECT * FROM users WHERE Email=%s",(email,))
        user = curl.fetchone()        

        if len(user) > 0:
            if user["Password"] == password:               
                session['Email'] = email
                session['Nickname'] = user["Nickname"]
                return render_template("profile.html")
            else:
                return "Error password and email not match"
        else:
            return "Error user not found"
    else:
        return render_template("login.html")
  

@app.route('/logout')
def logout():
    session.clear()
    return redirect(url_for("home")) 

@app.route("/signup", methods=["GET", "POST"])       
def signup():
    if request.method == 'GET':
        return render_template("signup.html")
    else:
        nickname = request.form['Nickname']
        firstName = request.form['First_Name']
        lastName = request.form['Last_Name']
        email = request.form['Email']
        password = request.form['Password'].encode('utf-8')
        
        hash_password = bcrypt.hashpw(password, bcrypt.gensalt(14))

        cur = mysql.connection.cursor()
        cur.execute("INSERT INTO users (Nickname, First_Name, Last_Name, 
        Email, Password) VALUES (%s,%s,%s,%s,%s)",(nickname,firstName,lastName,email,hash_password,))
        mysql.connection.commit()
        return redirect(url_for('home'))

if __name__ == '__main__':
    app.secret_key = 'bb8ef1d0a8de0bf09b4b2aaee861a7d5'
    app.run(debug=True)

和 html 形式

    <form action="/signup" method="POST">
    <input type="text" class="form-field" name="Nickname" placeholder="Nickname">
    <input type="text" class="form-field" name="First_Name" placeholder="First Name">
    <input type="text" class="form-field" name="Last_Name" placeholder="Last Name">
    <input type="email" class="form-field" name="Email" placeholder="Email">
    <input type="password" class="form-field" name="Password" placeholder="Password">
    <button type="submit" class="signup-btn">SIGNUP</button>
    </form>

<form action="/login" method="POST">
  <input type="email" class="form" name="Email"><br>
  <input type="password" class="form" name="Password"><br>
  <button type="submit" class="login-btn">LOGIN</button>
</form>

很难准确找出问题所在,因为我们缺少 MCVE 错误跟踪 ,无论如何我们至少可以猜测可能是什么原因.

虚线

首先,你在这一行有问题:

password = b'password'

您从未存储任何用户密码,而是它们都已被 password 值覆盖。在您的函数中注释掉这一行,您将能够存储用户输入的密码而不是虚拟值。

很遗憾,由于您丢失了原始用户信息,因此无法恢复已存储的密码。

工作流程

然后我们可以确认bcrypt按预期工作:

import bcrypt
saltp = bcrypt.gensalt(14)                       # b'bQmgF.1F4dTKeb8o8dprEu'
hashp = bcrypt.hashpw('abcdef'.encode(), saltp)  # b'bQmgF.1F4dTKeb8o8dprEuo2T2Y908hdZan9fb.LDWDuibPl/SLpm'
bcrypt.checkpw('abcdef'.encode(), hashp)         # True

从上面的这个片段,你应该尝试你的过程的所有步骤(添加 MySQL I/O 和新密码)以突出显示导致问题的步骤:

  • 在客户端使用区域设置收集的密码 (str);
  • 在服务器端使用 bcrypt (bytes) 对密码进行哈希处理;
  • 存储在 MySQL 中的密码哈希(受第一个错误的影响,我们仍然不知道您存储它的类型,是否必须 escaped,请阅读评论)
  • 从 MySQL 检索到密码哈希;
  • 使用 bcrypt 将密码哈希与用户输入进行比较;

危险

我的猜测: 问题出在 Flask 和 MySQL 之间,因为转换问题 bytesBLOB) 与 str (TEXT)。这很可能是您必须使用 user["Password"].encode('utf-8') 进行调整的原因,但它可能引入了另一个错误,因为您没有转义散列密码:您可能需要转义散列密码,因为 您正在尝试在文本字段中存储二进制数据.

我的建议: 在密码流程的每一步,检查 password/hash 值并确认您正在处理您认为的内容。当出现差异时,您将确定错误的来源。如果您仍然需要帮助,请在 POST 中明确描述。

谢谢,但这(我认为)正是我所拥有的。 我不知道为什么我有错误 我有 .hashpw 对密码进行哈希处理并将其存储在数据库中,这没关系,我看到数据库中的密码已加密,但是 .checkpw 用于将表单中的密码与密码进行比较在数据库中失败,说 Invalit salt 代码正是这样比较:

if bcrypt.checkpw(password, userPassworddb):

其中 password 是用户在登录表单中已经输入的密码 .encode('utf-8') 和 userPassworddb 是数据库中加密的密码(也需要转换 userPassworddb.encode('utf-8') 因为如果我不这样做,调试器会说我需要在比较之前进行编码)

在 html 的登录中,我有这个:

<form action="/login" method="POST">
  <input type="email" class="form" name="Email"><br>
  <input type="password" class="form" name="Password"><br>
  <button type="submit" class="login-btn">LOGIN</button>
</form>