0

Working with flask python. When i try to compare the hashed password encrypted with bcrypt.hashpw() say invalid salt.

Now i test it and if i put this if statement woks but only if in the password field in the html form i paste the password hashed (the thing is that i need to put the normal password) So the comparation i ok the form fiel in html and the connection to the db to take the user password works only fails when i need to put bcrypt.checkpw(password_in_the_login_form.html, password_hashed_in_the_db) That says Invalid Salt every time, here my code:

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)

And the html forms

    <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>
AMITIEL23
  • 13
  • 1
  • 3

2 Answers2

0

It is difficult to exactly pin out what is going wrong because we lack a MCVE and error traces, anyway we can at least guess what may be the cause.

Dummy line

First, you have a problem at this line:

password = b'password'

You never stored any user password, instead they all have been overridden by the password value. Comment out this line in your function and you will be able to store user input password instead of a dummy value.

Unfortunately, there is no recovery for already stored password as you have lost the original user information.

Working flow

Then we can confirm that bcrypt works as expected:

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

From this snippet above, you should try all steps of your process goes trough (add MySQL I/O with fresh passwords) to highlight which one is causing the issue:

  • Password collected with locale at client side (str);
  • Password hashed using bcrypt (bytes) at server side;
  • Password hash stored in MySQL (affected by the first bug, we still have no clue on what type you stored it and if it must escaped or not, please read comment)
  • Password hash retrieved from MySQL;
  • Password hash compared against user input using bcrypt;

Jeopardy

My guess: the problem resides between Flask and MySQL, you are not storing what you think it is because of casting problem bytes (BLOB) vs str (TEXT). This is most likely why you had to tweak things with user["Password"].encode('utf-8') but it may have introduced another bug because you haven't escaped your hashed password: you probably need to escape hashed password as you are trying to store binary data in a text field.

My advise: at every step of the password flow, check password/hash values and confirm you are handling what you think it is. When a discrepancy occurs, you will have identified the source of a bug. Then explicitly describe it in your POST if you still need help.

jlandercy
  • 7,183
  • 1
  • 39
  • 57
  • Still the same error. Before in my code i didnt have the password = b'password' – AMITIEL23 Aug 03 '20 at 13:05
  • Thanks a lot but yes the first line in b'password' i deleted in the first try thx – AMITIEL23 Aug 05 '20 at 11:43
  • Okay now i tested and the issue is in the line bcrypt.checkpw(password, hashed_password) I edited the code and now in the if statement i put if the password hashed stored in the database is the same like the password that i put in the form redirect to the profile.html and it redirect but i need to put the password hashed... i copied paste from my db look all the code ill edit my post – AMITIEL23 Aug 05 '20 at 13:46
0

Thanks but this is (i think) exactly what i have. I dont know why i have the error i have the .hashpw that hash the password and store it in the db and this is okay, i see the password in the db encrypted but the .checkpw to compare the password in the form to the password in the database fails, says Invalit salt the code is this exactly to compare:

if bcrypt.checkpw(password, userPassworddb):

Where password is the password that the user put in the login form with already .encode('utf-8') and userPassworddb is the password encrypted in the database (need too convert userPassworddb.encode('utf-8') cause if i dont do it the debugger says that i need to encode before comparing)

In the login from in html i have this:

<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>
AMITIEL23
  • 13
  • 1
  • 3
  • This is not an answer, you should update your post instead. At this point this is very difficult to help you without having a [mcve] to reproduce the issue. You definitely need to check the complete flow, when you will find where discrepancy are you will have a good clue on what is going wrong. My guess you do no store what you think because you are dealing with bytes. You thought you solved it with encode but you may need to escape as well. – jlandercy Aug 05 '20 at 05:13