I've written a method for hashing passwords by using hashlib. I allow the user to send a password through a POST method, which is received by Flask and the password is subsequently hashed so that the hash can be checked against a stored var to see if it's the same.
It works great both when a correct or an incorrect password is sent for the first time. But if the user sends a wrong password on the first POST and then tries again with the correct password, it fails. (One could also think of it as failing if the first try was a success and the user keeps on trying, but I don't care about that for now.)
I was able to narrow the problem down to hashlibs update function
hash.update(arg) Update the hash object with the string arg. Repeated calls are equivalent to a single call with the concatenation of all the arguments: m.update(a); m.update(b) is equivalent to m.update(a+b).
I wanted to know how can I disable the concatenation upon repeated calls. It doesn't matter if it's a hacky workaround.
Here's my code in case it's useful:
h = hashlib.sha256()
VALID_USERNAME = 'admin'
VALID_PASSW_HASH = "210ce034be6d826a451a4261d70494148c5d7101627335ccacf8e00a711bcc5d"
@app.route('/api/queue/auth', methods=['POST'])
def auth():
username = request.json.get('username')
password = request.json.get('password')
if bool(username) is False or bool(password) is False:
return "\nPlease fill in both fields.\n", 400
passwordBytes = password.encode(encoding='UTF-8',errors='strict')
h.update(passwordBytes)
if h.hexdigest() != VALID_PASSW_HASH or username != VALID_USERNAME:
return "\nPlease check your username and password, and try again.\n", 401
r.set('auth', 'true')
return "Access Granted.\n", 200
Additional notes:
- the "r.set" line (above the last one) is just because it later does something with Redis.
- i've checked that passwordBytes always returns the same encoding when the same password is provided (it's deterministic)
- i've also checked that h.hexdigest() is returning something different if the same password is provided on the first try or on another try. So taking into account these two points, we can be sure that the problem lies in h.update(), probably because of the concatenation feature.
Just move the first line out of the global scope into the
auth()function:or even better, refactor the hashing of the password to a different function: