pythoncryptographysha256hashlibcryptographic-hash-function

How can I disable concatenation when using hashlib's update method?


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:


Solution

  • Just move the first line out of the global scope into the auth() function:

    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 = hashlib.sha256()
        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
    

    or even better, refactor the hashing of the password to a different function:

    VALID_USERNAME = 'admin'
    VALID_PASSW_HASH = "210ce034be6d826a451a4261d70494148c5d7101627335ccacf8e00a711bcc5d"
    
    def hash_password(password):
        passwordBytes = password.encode(encoding='UTF-8',errors='strict')
        h = hashlib.sha256()
        h.update(passwordBytes)
        return h.hexdigest()
    
    
    @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
        if hash_password(password) != 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