Everything I know about storing passwords
Jun. 13th, 2012 11:07 amOK, everything I know about storing passwords in databases is:
* Offering a password strength meter is helpful. Insisting a password is long is possibly useful. Mandating complicated requirements about special characters that aren't documented is NOT helpful.
* Combine the password with a salt.
* The salt should be stored in the database, it need NOT be stored encrypted in any way
* The salt should be unique across all sites (ie. do NOT use the same salt for all passwords, nor use the username/email address as the salt. I can't remember is using a unqiue but predictable salt like sitename+username MIGHT is bad or not, but a random salt should be fine.)
* Combine the password with the salt, hash it, and store the hash in the database
* Use a password hash designed for the purpose (bcrypt, etc), not a cryptographic hash (md5). This will run a hash on the input thousands of times. If you don't, brute-forcing the passwords can be nearly trivial. Never use a non-cryptographic hash function -- that means one that's hard to reverse by chance, but may be easily reversible by malicious people.
* Use a pre-existing, well known library to do the hash.
* Whatever hash is currently best will be dangerously weak in five years time. I can't remember which is best (I've never had to do this). Don't memorise one and stick to it, go on stack overflow, ask which are the three best now, and pick one. Ideally you will know the pros and cons of different functions, but going with one of the industry standards is probably the least-risky.
* If you have any clever ideas for improving the process, DON'T. At least without running them by an expert (stackoverflow can probably tell you why they're stupid in a few minutes). SEVEN TIMES NEVER, never ever use a cryptographic function you implemented yourself, unless it's been extensively tested by a cryptographic community.
* You should never be able to recover a plain text password for a user in any way. If you can, you're doing something wrong.
* If someone forgets a password, offer an easy-to-use one-time password-reset link via email. Don't email plain-text passwords.
* Don't offer secret questions where the answers are less secure than a password.
* I have almost certainly made at least one serious error above. Don't rely on this, find something written by an expert.
* Consider open-id so someone else can do all this. For something more secure, you should probably use two-factor authentication implemented in some non-stupid way.
* There can be exceptions to this, where reduced security is a reasonable trade-off. But don't start by assuming that you're one of those cases. Even on a crappy throw-away website, you might not implement everything, but don't do any of the things that are bad.
And that's what I know as a non-expert, who's never done this, and hopes never to have to do this, from occasionally browsing best-practice discussions at stack overflow. That's probably the MINIMUM you can know and not be negligent, and is riddled with errors, simplifications, and miscommunications. If you know LESS than this, and are running a big company, you should probably hire someone who knows what they're doing to handle your passwords.
* Offering a password strength meter is helpful. Insisting a password is long is possibly useful. Mandating complicated requirements about special characters that aren't documented is NOT helpful.
* Combine the password with a salt.
* The salt should be stored in the database, it need NOT be stored encrypted in any way
* The salt should be unique across all sites (ie. do NOT use the same salt for all passwords, nor use the username/email address as the salt. I can't remember is using a unqiue but predictable salt like sitename+username MIGHT is bad or not, but a random salt should be fine.)
* Combine the password with the salt, hash it, and store the hash in the database
* Use a password hash designed for the purpose (bcrypt, etc), not a cryptographic hash (md5). This will run a hash on the input thousands of times. If you don't, brute-forcing the passwords can be nearly trivial. Never use a non-cryptographic hash function -- that means one that's hard to reverse by chance, but may be easily reversible by malicious people.
* Use a pre-existing, well known library to do the hash.
* Whatever hash is currently best will be dangerously weak in five years time. I can't remember which is best (I've never had to do this). Don't memorise one and stick to it, go on stack overflow, ask which are the three best now, and pick one. Ideally you will know the pros and cons of different functions, but going with one of the industry standards is probably the least-risky.
* If you have any clever ideas for improving the process, DON'T. At least without running them by an expert (stackoverflow can probably tell you why they're stupid in a few minutes). SEVEN TIMES NEVER, never ever use a cryptographic function you implemented yourself, unless it's been extensively tested by a cryptographic community.
* You should never be able to recover a plain text password for a user in any way. If you can, you're doing something wrong.
* If someone forgets a password, offer an easy-to-use one-time password-reset link via email. Don't email plain-text passwords.
* Don't offer secret questions where the answers are less secure than a password.
* I have almost certainly made at least one serious error above. Don't rely on this, find something written by an expert.
* Consider open-id so someone else can do all this. For something more secure, you should probably use two-factor authentication implemented in some non-stupid way.
* There can be exceptions to this, where reduced security is a reasonable trade-off. But don't start by assuming that you're one of those cases. Even on a crappy throw-away website, you might not implement everything, but don't do any of the things that are bad.
And that's what I know as a non-expert, who's never done this, and hopes never to have to do this, from occasionally browsing best-practice discussions at stack overflow. That's probably the MINIMUM you can know and not be negligent, and is riddled with errors, simplifications, and miscommunications. If you know LESS than this, and are running a big company, you should probably hire someone who knows what they're doing to handle your passwords.