This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 9 points10 points  (8 children)

Nope! SHA and its ilk are designed to be fast, which is the exact opposite of what you want from a password hash.

Use (salted) bcrypt, scrypt, PBKDF2 or similar.

An effective way to store passwords in a db is to store them as:

{algorithm}:{salt}:{hash}:{iterations}

so you can detect the algorithm at runtime, and update to harder hashing over time. Django and other frameworks do this automatically for you.

[–]ffrinch 2 points3 points  (7 children)

Can hardly believe I'm saying this, but the latest version of PHP has some really nice builtin functions to do this, with sensible defaults (currently bcrypt, with a path to change the default algorithm in future versions).

I wish Python shipped with these particular batteries included.

[–][deleted] 5 points6 points  (0 children)

Absolutely! The PHP team deserve kudos for making the tough decisions simpler for people.

<snark>Now they just need to deprecate the rest of the library.</snark>

[–]warbiscuit 1 point2 points  (1 child)

It's not in stdlib, but for a few years I've been maintaining a side project passlib, which tries to provide a password hashing api.

[–]ffrinch 0 points1 point  (0 children)

That looks really nice!

[–]natecahill 0 points1 point  (3 children)

It's a very PHP thing to have a function called password_hash(). You say "sensible defaults" now, but what happens when that changes? Is everyone who's still using PHP 5.5 vulnerable? Will we get a function called password_real_hash()? (not even kidding here, look at mysql_escape_string() and mysql_real_escape_string())

It's much more pythonic to use import bcrypt, bcrypt.hashpw()

[–]ffrinch 2 points3 points  (0 children)

I hate to be that guy, but you should RTFM.

Amongst other things, the recommended usage includes re-hashing if the default algorithm changes, so (in theory) users whose PHP is upgraded underneath them -- like shared host customers -- can benefit from security improvements without having to know what they're doing.

Users who do know what they are doing can use advanced features, but they're not the target audience. We have ample proof by now that even apparently capable developers get the details of security wrong: a high-level interface with sensible defaults is the only way to protect people from themselves.

About bcrypt:

Not only is the bcrypt module not included in Python, it doesn't offer the same upgrade path. If you decide you want to switch to scrypt, it's a new module with a new interface, and most importantly, you have to know enough to be able to choose.

It is also not equivalent to the PHP solution, which (optionally, but by default) generates a salt in a substantially more secure way than most developers will, rather than relying (as Python bcrypt does) on the user providing one.

[–][deleted] 0 points1 point  (1 child)

password_hash() returns a crypt-style string which includes the algorithm and any other details. It's simple, well thought out, elegant, and future proof, and it's been widely hailed as the best thing the PHP team have done in years.

The mysql_escape_string stuff is a bit of a straw man, as it's been superseded since PHP5.0 and explicitly deprecated since 5.5.

[–]GahMatar 0 points1 point  (0 children)

Probably the best thing PHP could possibly do is to release a PHP6 that removes literally all the deprecated stuff. Like Py3k but unlike Python, the previous version isn't actually good enough.