Brypt and comparing hashes

This isn’t an issue I’m having with any of the tests, more of a syntax question, I guess? basically, why do we need the compare() and compareSync() functions in bcrypt? can’t the same thing be accomplished with bcrypt.hashSync(userInput, 12) === storedHash (or something analogous with the asynchronous function)?

The reason you don’t compare hashes with equality is because the === operator short-circuits, and the compare/compareSync functions do not. I’ll explain why this is important after I explain short-circuiting. When you compare two strings, like "foobar" and "fooxyz" using the === operator, the comparison will go letter-by-letter in each string, then stop and return false at the fourth letter where they differ, without bothering to compare the rest of the string. That’s called “short-circuiting”. This makes equality testing faster, but that’s exactly the problem with cryptographic hashes, because it opens the door to something called a timing attack:

A timing attack is where you can discover a secret just by measuring the time it takes to perform some short-circuiting operation on it. Imagine you had a password that hashed to bftq76hfkjhg (keeping it super short for demo purposes). Now pick a password to guess, and let’s say it hashes to ghertha4taf3. Using the === method of comparison, this short-circuits on the very first letter, so it returns faster than comparing a password that hashed to bftq76wyr7zv which starts differing at the 6th letter. Using this timing information, you can start constructing hashes that take longer to compare until you’ve cracked all 12 letters.

The compare/compareSync functions do not short-circuit, however, and will compare all 12 letters regardless of when they stopped matching. By taking the exact same amount of time to compare every hash, attackers don’t get any timing information out of it.

Since timing attacks take a lot of attempts, this vulnerability isn’t usually a big deal on properly hashed login passwords, owing to the nature of bcrypt (and similar) itself and the fact that a decent password system will have a lockout after multiple failed attempts. But the same idea can apply to other secrets within a program that are just as critical as passwords, such as encryption keys, and timing attacks work on those just as well.

Using a non-short-circuiting algorithm to compare keys is one step toward mitigating timing attacks, though what we’re finding with modern CPU architectures is that that isn’t always enough. If you really want to give yourself nightmares, google for “Spectre and Meltdown attacks”, which are both timing attacks against your CPU itself.

1 Like

Thank you for this info ^^ it was very enlightening. My apologies for taking so long to respond, I got side-tracked when I was first reading this looking up spectre and meltdown attacks.