When RSA 768 came within reach of brute forcing, everybody moved to RSA 2048 and RSA 4096. To make a similar leap in attacker cost for iterative hashing solutions, your login prompt would force users to sit idly for minutes, hours, or maybe even days. And making this change systemically is still underway, taking years.
Because the cost function of iterative hashing is identical between defender and attacker, you cannot pad your security in a way that is robust and generalizable against attacker capabilities in a reasonable future timeframe. How many solutions that use PBKDF, scrypt, etc, have gone back and changed their cost function (i.e. iteration count) after a year? After 3 years? After 5 years?[1] Do they tune their cost function to 8-character passwords? 10-character passwords?
And no amount of iteration within a reasonable time frame is going to prevent an attacker from cracking prototypically insecure passwords. Bitcoin becomes exponentially more difficult to mine over time. As a practical matter there's no limit to the number of bad passwords in a websites database, no matter the length.
Once you've implemented password salting, removing an attacker's ability to exponentially decrease his cost function for the next password cracking attempt, you're just putting lipstick on a pig. For people who care about good passwords, iterative hashing is irrelevant--a few extra random characters adds more cost than the authenticator would ever achieve with an increased iteration count. For all practical purposes, an authenticator's duty to attend to low-level algorithmic details ends at salting. After that, he maximizes security by redirecting all available effort to securing his infrastructure, catching bad passwords, and supplementing or replacing authentication with a passwordless mechanism.
The emphasis on specific hardware is misguided. Real-world attackers don't use FPGAs, they use public clouds and botnets. Perhaps some governments use bespoke hardware, but even then the real gains in performance still come largely from the clustering of commodity hardware. Look at supercomputers--they moved away from bespoke hardware decades ago.
Password hashing solutions that tout memory hardness and the inability to easily create bespoke hardware crackers are something dangerously close to snake oil. The features are technically legitimate but largely irrelevant in the context of real-world security. Like most snake oil, it's not that they don't add any absolute value whatsoever, but rather the magnitude of the benefit is greatly exaggerated, while the opportunity cost in misdirected resources greatly underestimated. Quibbling over a few ephemeral bits of additional attacker complexity is not a place you want to find yourself.
[1] OpenBSD was one of the first, if not the first, to both add a memory hardness aspect to their hashing algorithm and a dynamic cost function with iteration, with iterated Blowfish. But they went years, if not over a decade, before updating the default iteration count. And Blowfish is of course no longer really considered memory-hard. It's more or less an abandoned idea in OpenBSD.
> Because the cost function of iterative hashing is identical
> between defender and attacker
In the same sense as paint one can once is equivalent in financial terms to paying once cent trillion times.In the real-world, at scale the only relevant metric to his cost is the entropy of the password, which iterative hashing doesn't magically increase.
If you find it cost-effective to slap a `for (i = 0; i < 10^12; i++)` loop around your hash, you should assume it's cost-effective for your attacker as well.
These are fundamental assumption you should make in the absence of very specific exceptions not typically applicable to attack modeling of public internet services.
The use of these overwrought hashing schemes doesn't change the fundamental cost dynamic for brute-forcing password hashes. At best it's the same today as it was 30 years ago. At worst, because of botnets, he can scale must more cheaply than you.
The arguments in favor of these schemes are pragmatic, not scientific. But they're predicated on the defender constantly keeping up to date with hardware advancements as that margin is thin and evolving rapidly. Worse, it completely ignores the fact that if I've recovered the password digest for one account, I've likely recovered the digests for dozens, hundreds, or perhaps thousands of accounts with equivalent authorizations. Because of exponential cost differences between good passwords and bad passwords, and the prevalence of bad passwords, I can profitably filter out the good passwords by setting a fixed absolute per-password cost ceiling, substantially lowering my asymptotic costs.
Iterative and memory-hard password schemes are simply fighting an uphill battle. Once you move beyond salting you're just throwing good money after bad money by attempting to secure bad passwords.
Good passwords are already secure; bad passwords can't be fixed by the hashing scheme du jour.
> If you find it cost-effective to slap a `for (i = 0; i < 10^12; i++)` loop around your hash, you should assume it's cost-effective for your attacker as well.
If your work factor is higher, it takes much longer to brute force a password. On my laptop, bcrypt with work factors 13 and 14 take ~650ms and ~1100ms, respectively. In comparison, SHA256 takes 0.110ms.
A database of passwords hashed with SHA256 will take days, maybe weeks to recover most of the passwords through brute force. With bcrypt, it would take months or years.
This article[1] has some numbers (although they're a bit outdated now):
> How much slower is bcrypt than, say, MD5? Depends on the work factor. Using a work factor of 12, bcrypt hashes the password yaaa in about 0.3 seconds on my laptop. MD5, on the other hand, takes less than a microsecond.
> So we’re talking about 5 or so orders of magnitude. Instead of cracking a password every 40 seconds, I’d be cracking them every 12 years or so. Your passwords might not need that kind of security and you might need a faster comparison algorithm, but bcrypt allows you to choose your balance of speed and security. Use it.
Or it will take seconds on special purposed hardware, not much longer than salted sha256. In the mean time you'll have made poor security decisions based on the invalid assumption that your attacker will need months or years of compute...
EDIT: Besides, bcrypt is not even the "best" hash function we have available. If you're concerned about GPUs and FPGAs, there's argon2id which has much stronger guarantees than bcrypt.