22

Timing attacks can have a devastating impact in scenarios where the secret is involved, often in cases where byte-wise array comparison is used.

Now there are those that advertise using constant time array comparison in any situation where data is compared that was derived from a secret, not only when comparing the secret itself. The rationale is "better safe than sorry". Although this is fine, I'm still wondering if it is really necessary all the time.

A particular case where I would tend to think that constant time array comparison is probably unnecessary is comparing stored password hashes with those provided by the user. Let's assume the password was properly stored using for example bcrypt. If the application uses short-circuiting array comparison, an attacker could gain information about the "number of correct bits" of arbitrarily chosen passwords by evaluating the time it takes for a response.

Now my question is whether this can be transformed into a "better than brute force" attack? Is there a possibility for an incremental attack, i.e. is it possible to construct a password with n+1 correct bits from a password with n correct bits other than using brute-force guessing?

I would be interested in the following:

  • Existence of theoretical results that prove that such an attack is (in-)feasible for one-way (compression) functions that do not assume the hash function to be (pseudo-)random
  • Negative/positive results for real-world hash functions such as MD5, SHA-1 etc.
emboss
  • 4,298
  • 1
  • 16
  • 17
  • https://crypto.stackexchange.com/questions/40433/is-it-necessary-to-worry-about-timing-attacks-when-comparing-sha256-or-argon2-ha - "Is it necessary to worry about timing attacks when comparing SHA256 or Argon2 hashes?" – Roland Pihlakas Feb 13 '20 at 08:56

1 Answers1

23

Short version: I think there is no danger doing short-cut comparison of salted hashes of passwords, if the salt is hidden to the attacker.

Long version:

Using timing attacks in this case will in no way tell an attacker more than what he would know if he had the actual stored hash and salt ... and brypt's security parameter (iteration count exponent) should be chosen such that even knowing the hash and salt would not give the attacker a significant enough advantage to derive the password (since he would have to brute-force the password from this).

On the other hand, if the attacker does know neither the used salt nor the stored hash, I would guess that a timing of the comparison of calculated and stored hash will not give any information at all, since every (even single bit) change of the password input will result in a completely different hash. (This applies to every pseudo-random function, not only bcrypt. We actually need only the avalanche effect here.) See below for a more formal elaboration.

Other than this, normally the hashing process itself is included in the measuring, which takes much longer than the final comparison at the end, and thus will dominate the total measured time. I don't know how much this hashing time will variate, though.


Mathematical version:

Now my question is whether this can be transformed into a "better than brute force" attack? Is there a possibility for an incremental attack, i.e. is it possible to construct a password with n+1 correct bits from a password with n correct bits other than using brute-force guessing?

So we have a function c_h(y), which is the number of leading bits matching between H(s, y) and h. Let m be the total number of bits of H's output.

Assume we have an algorithm A which can do your attack, i.e. an algorithm which, for a hash h (unknown to A) and a given message x with c_h(x) = n, finds a message x' with c_h(x) >= n+1, in time better than exponential in n. (Simple brute-forcing the hash is exponential in n.) We can assume that this algorithm has O(1) oracle access to c_h(y) for arbitrary y.

Then we can from this construct an algorithm B which will do a preimage attack on a given hash h and salt s, i.e. finds a message z with H(s,z) = h. It works as follows:

  • The oracle for A is simply done by calculating H(s,y) and comparing it with h, counting the correct bits until the first non-match.
  • We choose an arbitrary message x_0, calculate n_0 = c_h(x_0).
  • For each i > 0:
    • We pass x_(i-1) to A, and get back x_i with n_i = c_h(x_i) > n_(i-1).
    • if n_i = m, stop and return z = x_i.

The output of B is a preimage for (s, h).

As each n_i is larger than the previous one, this will take at most m passes through the loop, with each pass taking at most o(exp(n_i)) time, i.e. in total o(exp(m)). Thus we got a sub-exponential preimage-finding algorithm.

This shows that, assuming H is preimage-resistant, there can't be an algorithm which efficiently produces longer partial matches from shorter partial matches, given the match length as an oracle.

(I assume one can refine my timing approximation a bit better.)


Notes regarding the comments:

As the comment thread is getting quite long, I'll try to resume the important points here:

  • With weak passwords, an offline dictionary attack on password hashes will become feasible, which would be our algorithm B. This is why we want to choose the bcrypt work factor high enough.

    Still, I see no way to get from a fast B (offline preimage attack with given salt) to a fast A (online partial preimage finder from hash prefix length oracle) algorithm, only the other way around.

    I expect that even for functions which are preimage-broken there would be no easy way to get our online attack, as long as they still fit the avalanche criterion.

  • Real-life hash functions are not really random (which is caused by their iterative design), but this does not really affect their suitability for password hashing, which works on inputs shorter than the block size.

  • The important property here is preimage resistance, not collision resistance. (Every collision resistant function is second-preimage resistant, and second-preimage resistant functions are preimage resistant - though we usually expect a higher resistance against (second) preimage attacks than given by this reduction from collision resistance, due to the generic birthday attack to find collisions.) This means this proof applies to MD5 (which is broken collision-wise), as long as there is no preimage attack.

  • The proof above does not rely on the hash function being a random oracle, it just uses an oracle access to c_h(y), which abstracts the timing measure for the

Paŭlo Ebermann
  • 2,467
  • 19
  • 20
  • OK, it seems infeasible if we assume the hash function to be (pseudo-)random. But are there results for the weaker assumption of only a collision-resistant (compression) function? Regarding hashing dominating the comparison - statistics should still render it possible to find any bias, given a large enough set of samples. See for example [Remote Timing Attacks Are Still Practical](http://eprint.iacr.org/2011/232.pdf). – emboss Nov 25 '11 at 01:22
  • 1
    "_even knowing the hash and salt would not give the attacker a significant enough advantage to derive the password_" I disagree. **It would give the attacker a way to perform an offline, unbounded, dictionary attack on the password.** This is a strong attack on weak passwords, which is the standard assumption. (If it is guaranteed that passwords are strong, you do not need either salting or bcrypt - MD5 alone would be fine.) Without hash and salt, the attacker can only do an online attack, and the server can slow it down, so that only a few hundred passwords can be tried. – curiousguy Nov 25 '11 at 01:41
  • @emboss "_only a collision-resistant (compression) function_" Hug? – curiousguy Nov 25 '11 at 01:42
  • @curiousguy Today's hash functions are no (pseudo-) random functions. Collison resistance does not imply randomness per se. Maybe that could still allow the possibility of such an incremental attack for non-random hash functions? – emboss Nov 25 '11 at 01:52
  • @curiousguy Of course, we would prefer if the attacker wouldn't know hash and salt (i.e. couldn't do an offline attack), but a password should normally hashed in a way that even an offline attack (for example from a leaked backup copy of the database, or a rogue sysadmin) will not compromise the passwords. (The rest of my answer is trying to show that we won't get that much information.) – Paŭlo Ebermann Nov 25 '11 at 01:52
  • @emboss Actually, we don't know anything about the existence of collision-resistant, preimage-resistant or pseudo-random hash functions, nor whether our current hash functions are such (only that MD5 is not a good one). I can't really answer your question about which properties of hash functions are enough to guarantee this property ... though I suppose that a hash function where we have "related-output attacks" seems to also allow preimage attacks, and following this also to collision attacks. – Paŭlo Ebermann Nov 25 '11 at 02:03
  • @PaŭloEbermann Well, we can rule current iterated hash functions out as being random because of the existence of extension attacks - that is we *are* able to predict values of certain inputs for them. Random functions would forbid the "incremental attack", but I'm wondering about real life hash functions... – emboss Nov 25 '11 at 02:14
  • @emboss "_Collison resistance does not imply randomness per se._" collision resistance is not even relevant here – curiousguy Nov 25 '11 at 02:33
  • @emboss Extension attacks don't really apply for password hashing, where the input is actually shorter than the output. – Paŭlo Ebermann Nov 25 '11 at 03:13
  • @emboss "_Today's hash functions are no (pseudo-) random functions._" how do you define "(pseudo-) random"? – curiousguy Nov 25 '11 at 05:50
  • @curiousguy http://en.wikipedia.org/wiki/Random_function – emboss Nov 25 '11 at 11:02
  • @PaŭloEbermann Just saying that extension attacks are proof that SHA and colleagues are not random. I would be interested in theoretical results that do *not* rely on the assumption of randomness. – emboss Nov 25 '11 at 11:18
  • @emboss: By intuition, I would say your needed property is connected to the preimage-resistance (which is about the most basic property you could want for a cryptographic hash function), but I can't offer a proof. – Paŭlo Ebermann Nov 25 '11 at 12:27
  • @emboss: I added a sketch of a proof for preimage-resistant functions to my answer. – Paŭlo Ebermann Nov 25 '11 at 13:50
  • I thought a bit about your proof, and I think it's even possible to leave out the oracle at all? Assume the existence of A, then show we can conduct a preimage attack in less than exponential time in contradiction to the assumption of H being collision-resistant? I'm going to raise a bounty on this one, it's really important to me, so I would love to hear other impressions. But it's not that I wouldn't like your answer, I like it a lot! Just hoping that maybe someone can provide results for existing functions. Thanks again! – emboss Nov 27 '11 at 14:08
  • @emboss: A works by having this oracle (the timing measuring), and B provides this oracle to A (by using the easier direct hash implementation). B itself needs no oracle. Collision-resistance is a stronger property than preimage-resistance (CR implies PR), so this seems to work even for MD5 (which is not collision-resistant, but seems to still be preimage-resistant). (Note that we don't know if any existing functions are preimage-resistant at all.) – Paŭlo Ebermann Nov 27 '11 at 15:01
  • name one application where the salt is more difficult to obtain than the password hash. – rook Nov 27 '11 at 19:35
  • @Rook Is this comment targeted at me? As far as I can see, I did never write something about a secret salt, I only think about online attacks where the attacker has neither hash nor salt, additionally to the offline attacks where she has both. – Paŭlo Ebermann Nov 27 '11 at 19:43