This post truly is internet history. Complaining that there's alternatives today that solve the same problem better than bcrypt is beside the point. The fundamental insight hasn't changed, only the best available algorithm.
Articles like these set off a bit of a research fad in designing password hashes, which is great, but also created the impression that using the wrong password hash is like using SHA1 or 1024 bit RSA, which is not the case. By all means, use Argon2 if you like; it is "better", but not decisively so. Or just put PBKDF2, scrypt, bcrypt, and Argon2 on a wall and throw a dart.
The danger is in not using a password hash at all, but rather using a "salted hash".
OWASP has nice document: https://cheatsheetseries.owasp.org/cheatsheets/Password_Stor...
It boils down to this:
> Bcrypt is the most widely supported of the algorithms and should be the default choice unless there are specific requirements for PBKDF2, or appropriate knowledge to tune Argon2.
Per wikipedia:
> From 2004, the “NIST Special Publication 800-63. Appendix A,”[2] advised people to use irregular capitalization, special characters, and at least one numeral. It also recommended changing passwords regularly, at least every 90 days. This was the advice that most systems followed, and was "baked into" a number of standards that businesses needed to follow.
I work in a compliance heavy environment and have tried getting the rotation policy changed, but it's baked into so many contracts at this point it will take another 5+ years before we to the ~2018 era guidelines.
As a layman who has too many passwords that rotate too often to keep in memory effectively, I'd like to pass this along to our IT department. Can someone post a link to the NIST best password practices?
More recent designs such as scrypt and Argon2 force high memory usage as well as computation time, incurring little cost on the users but making ASIC and GPU attacks significantly less cost-effective.
Of course, any of these will still give better protection than plain cryptographic hashes.
Looks like for the typical case (~200ms calculating the hash) bcrypt beats argon2. I guess that’s what I understand from those discussions, I’m not an expert by any means. It is related with cache hardness: https://twitter.com/Sc00bzT/status/1149963675069026304
In particular, in terms of ASIC attacks, bcrypt and other non-memory-hard KDFs have extremely efficient implementations. Silicon is cheap, computation is cheap, memory access is extremely expensive- both in terms of time and power usage.
Here is an scrypt just in JS[1]. It will also run in the browser, if you need to hash client side for some reason. On node, it will use the built in crypto api which IIRC is a wrapper around openSSL so perf should be native. I'm not a big fan of the API, you have to concern yourself with buffers and normalization. Maybe that is important for non-latin alphabets? I don't actually know, I'm too anglo-centric.
Then there is good ol bcrypt[2]. Certainly the most mature, it has been around a while. Like [0], it also uses a native module with node-gyp.
All three support async/await so you can avoid blocking the event loop during expensive hashing operations. I should note I haven't really used any of them. I was just curious so I did some googling.
Based on your criteria, I think [0] fits the bill best. Very hard to forget the salt, as it is generated by default and stored with the hash.
I'm always really curious about other people's code, so I hope you don't mind me asking: I typically use a library/framework that handles details like password hashing. That said, sometimes i like to avoid libs and really understand every aspect. Can I inquire about your stack? Are you using express or koa or anything like that?
[0] https://github.com/ranisalt/node-argon2
const scryptParams = { logN: 15, r: 8, p: 1 };
async function hashPassword(password: string): Promise<string> {
const password_hash: Buffer = await scrypt.kdf(password, scryptParams);
return password_hash.toString("base64");
}
async function verifyPassword(hash, password): Promise<boolean> {
return await scrypt.verify(Buffer.from(hash, "base64"), password);
}I know that Litecoin used scrypt to harden it against GPU/ASIC mining, but GPU/ASIC miners ended up coming out anyways. With this in mind, is scrypt actually a better option than bcrypt?
The idea is to alert an application program to the need to regenerate the hash at the time it has the plaintext password in hand (when the user has just presented it for login).
This is a great idea; rehashing a long-standing bcrypt password with a larger work factor makes it safer.
And, an extension or new version of the runtime can add a new hashing scheme.
It would be sweet if other password-hashing APIs added the same kind of thing. User accounts can last far longer than LTS versions of software runtimes, and this can help future-proof them.
(Cracking Passwords with Cheap Hardware at Defcon):
Is Word Machine publicly available, or is it the sort of thing that has an audience of one?
And, unfortunately, wm has an audience of one. Mostly because I'm ashamed to share it.
Imagine every device has a cookie/token with 256-512 CSPRNG bytes which uniquely identify it. The server uses this as the exclusive means of authentication. For sensitive application scenarios, an in-app PIN mechanism can be used as a soft protective measure (e.g. Robinhood mobile apps use this). The device you initially sign up on can be used to activate additional devices by way of scanning a QR code, offline recovery codes, SMS, etc.
This model makes it so that a user has no username or password to remember. They just need to make sure they have a backup device and/or offline recovery options available. I find that side-stepping the problem altogether might be the best solution for all involved. Users loathe remembering passwords. Developers screw up password hashing constantly. Malicious actors should grow to strongly dislike this approach.
This also provides a much stricter chain of custody over how additional devices are added to an account. You have to already have a trusted device to bring another. Making the "What you have" (device) the first factor, and the "What you know" (i.e. pin code) the second factor seems to work out a lot better looking forward.
There's the hard part.
Go to the World of Warcraft forums and ask how many people have had trouble dealing with identity verification with Blizzard because they lost or destroyed their phone and no longer have access to the Blizzard Authenticator app and are therefore locked out of their account. Sure, the app will give you backup codes you can use to restore the Authenticator on a new device, but clearly very few people are actually recording those somewhere.
> Developers screw up password hashing constantly.
Developers should know better. There's no excuse for continuing to use poor/no hashing for password storage.
> Malicious actors should grow to strongly dislike this approach.
Not as much as you think. Considering how many people still think that fingerprints are secure, if stealing someone's device means having access to everything they have, then "your device is your password" is flawed. PINs and swipe patterns are trivial to shoulder surf.
Why would you pick one over the other? Or are both "pretty much fine" for most workloads and a casual user shouldn't worry too much?
bcrypt, scrypt, Argon2: it doesn't practically matter. Actual cryptographers don't stop recommending safe and well-tested algorithms just because newer ones have been published. There has been no cryptanalytic break in bcrypt or scrypt. The benefits of Argon2 are largely academic for common workloads.
So something like pbkdf2 is intended to be "CPU hard" ie: it bottlenecks you on CPU. Then people started using GPUs for pbkdf2.
So we got bcrypt, which is CPU hard and uses enough memory that a GPU stops being particularly practical.
And then people build ASICs to bruteforce bcrypt faster. So we got scrypt and argon2, which are memory hard.
But the thing is that even PBKDF2 is pretty good. You can always just bump up the iteration count for PBKDF2 to increase security. I use a combination of PBKDF2 and bcrypt myself (pbkdf2 on the frontend, bcrypt on the backend).
2011 https://news.ycombinator.com/item?id=2716714
2010 https://news.ycombinator.com/item?id=2004833
Discussed at the time: https://news.ycombinator.com/item?id=1091104
https://www.google.co.uk/amp/s/nakedsecurity.sophos.com/2013...
(Apologies for the blasted Amp link... on my phone)
There are constructions to avoid this problem but they are not commonly used.
But an article with that title would probably be less visible to the audience that really needs to read it.
Feeling glib, but passwords are hot potatoes best to avoid if you can. There are plenty of OpenID Connect providers to pass off the buck to, or an increasing number of "passwordless" options including the simple scheme of one-time codes delivered to user email addresses.
Only true if you don't know the salt. Of course, most folks store the hash and salt in the same table or column (Django).
Use argon2. Use argon2. Use argon2. Use argon2. Use argon2. Use argon2. Use argon2. Use argon2. Use argon2.
Finding a trusted 3rd party who's responsibility is to stay on top of it, is definitely the way to go if you're not in the security space. It's scary how many people don't understand the basics of hashing and encryption that have written authentication systems. When people ask me if we should do something like this, I normally say, "If you're asking me, then you probably already know the answer."
It does not. I agree with you that you shouldn't store passwords if you don't have to, but bcrypt and scrypt are still absolutely fine. You do not need to choose Argon2. Cryptographic algorithms shouldn't be deprecated just because something new came out, they should only be deprecated when there is a specific, published cryptanalysis that weakens them.