# Between a rock and a crazy place

## Difficulties making SQL based authentication resilient against timing attacks

13 Apr 2015

I've been thinking about how to do an authentication scheme, that uses some kind of relational database (it doesn't matter specifically, that the database is relational, the concerns should pretty much apply to all databases) as a backing store, in a way that is resilient against timing side-channel attacks and doesn't leak any data about which usernames exist in the system and which don't.

The first obvious thing is, that you need to do a constant time comparison of password-hashes. Luckily, most modern crypto libraries should include something like that (at least go's bcrypt implementation comes with that).

But now the question is, how you prevent enumerating users (or checking for existence). A naive query will return an empty result set if the user does not exists, so again, obviously, you need to compare against some password, even if the user isn't found. But just doing, for example

if result.Empty {
// Compare against a prepared hash of an empty password, to have constant
// time check.
} else {
}


won't get you very far. Because (for example) the CPU will predict either of the two branches (and the compiler might or might not decide to "help" with that), so again an attacker might be able to distinguish between the two cases. The best way, to achieve resilience against timing side-channels is to make sure, that your control flow does not depend on input data at all. Meaning no branch or loop should ever take in any way into account, what is actually input into your code (including the username and the result of the database query).

So my next thought was to modify the query to return the hash of an empty password as a default, if no user is found. That way, your code is guaranteed to always get a well-defined bcrypt-hash from the database and your control flow does not depend on whether or not the user exists (and an empty password can be safely excluded in advance, as returning early for that does not give any new data to the attacker).