According to the OWASP guidelines:
Authentication failure responses should not indicate which part of the authentication data was incorrect. For example, instead of "Invalid username" or "Invalid password", just use "Invalid username and/or password" for both. Error responses must be truly identical in both display and source code.
Let's say a naive implementation of this (in pseudo code) is as follows:
function authenticate(username, password): let hashed_password = get_user_from_model(username) if user is not found: return "Invalid username and/or password" if verify_bcrypt(password, hashed_password): return "Authenticated" else: return "Invalid username and/or password"
Assuming that the
get_user_from_model function takes a neglible amount of time and the
verify_bcrypt takes 400ms, an attacker may be able to deduce whether the function returned when the password was invalid or username was invalid using a timing attack. What would be the best practice in order to stop this? Is something like sleeping for a constant amount of time a good idea? How would this work across different systems that might take different amount of time to verify the hash?