Safely Storing Passwords
My first post on here, hope it's well received!
In light of recent database hacks (MtGox, Sony, etc) - How to safely store passwords is at the front of every developers mind.
Almost every dev knows that storing plaintext passwords is a bad idea, but most don't realise that storing a SHA hash should also be considered a bad idea.
The SHA + salt pattern has been widely adopted, however modern hardware can brute force such hashes in a reasonable time using CUDA. In the near future it's not inconceivable that arbitrary hashes could be brute forced in seconds.
Bcrypt solves the problem of hardware increasing in power, rendering your chosen hashing function obsolete. I suggest reading How To Safely Store A Password, by Coda Hale for the hairy details.
To use bcrypt in perl, you can use Crypt::Eksblowfish::Bcrypt.
To help people follow these best practices, I have wrote a Dancer plugin that simplifies created and verifying bcrypt hashes. Dancer::Plugin::Bcrypt. Any feedback is welcome :)
Always happy to see people advocate bcrypt and even more so to provide actual code to go with it. :D
A little request though: Maybe it would be useful to add a convenience function that takes a plaintext password and a bcrypt hash and returns a boolean for whether they match?
Interesting post! Any thoughts on how to safely transmit the passwords? Back in Ye Olde Days, when I still fancied myself a web developer, I liked using md5 because I could easily calculate the hash client side and not transmit plaintext over the wire. I'm guessing that strategy won't work very well with a more complicated password hashing algorithm like bcrypt. Is https good enough that this isn't a real concern?
@Mithaldu - I just merged a pull request that provides that feature, expect it to land soon :)
@Carey Tilden - https would be the way to do that. If you calculate the md5 hash client side and use that to authenticate with, then the md5 hash is the password, and you're effectively storing plaintext passwords (or storing a hash of the hash of the actual password)
General rule of thumb when it comes to crypto is to not try and do it yourself. Pick a library, and use it.
I like the idea of this module - it makes it very trivial to get password handling correct.
I would add though, as pointed out by mst, that it's not the only way or necessarily the best way; for instance, if you're using DBIx::Class, then you should probably look at DBIx::Class::PassphraseColumn for a way to handle it automatically within your DBIC model.
I do like the fact that this plugin offers easy secure password handling with a couple of lines of code added to your Dancer app, though. Simplicity is often good, especially when it could make the difference between someone doing the right thing, and implementing their own insecure scheme, or worse still, storing plain text passwords.
@James Aitken Oh, my question was mainly whether https is the best thing for protecting passwords over the wire. I guess I should have left out the md5 stuff, it only muddled my question. Which you answered, so I might be muddling it even more now. :-)
Either way, thanks for posting!