To protect against password brute-forcing, and to protect against timing attacks trying to detect valid usernames, I want my login process to take a constant amount of time regardless of successful authentication or not. In short I always want my login process to take say 1000ms (assume either outcome takes fractions of that time), regardless of the outcome. What’s the best way to accomplish this in Java? This is my current thinking:
class ConstantDuration<T> implements Callable<T> {
ConstantDuration(Callable<T> task,long duration) {
this.task = task;
this.duration = duration;
}
public T call() throws Exception {
long start = System.currentTimeMillis();
long elapsed = 0;
T result = null;
try {
result = task.call();
} finally {
elapsed = System.currentTimeMillis() - start;
}
if ( elapsed < duration ) {
Thread.sleep(duration-elapsed);
}
return result;
}
}
Obviously, you’ll want to move sleeping into the finally block so it also occurs if task throws an Exception (for instance a PasswordExpiredException?).
The other problem is handling the case
elapsed > duration. You say that never happens, but are you sure? What if your database query gets stalled by a lock? Assuming you want to deny authentication in such an event, you could do:(You’ll need to add proper exception handling, of course)
I am not sure though this is a good way to defend against brute force attacks, though. Instead, we invalidate a user’s login after the third consequtive failed login attempt (for a certain period of time or until an administrator unlocks the account). Mention somewhere that you do this, and nobody has a reason to brute force passwords.