Proper password hashing

99 views
Skip to first unread message

Glendon Solsberry

unread,
Sep 5, 2012, 1:06:03 PM9/5/12
to se...@googlegroups.com
I've read a million different ways to "properly" hash a password. Most of the examples aren't very explanatory though. Can we create "the end all, be all" of explanations on how to properly hash a password (and how to store it, retrieve it, etc)?

This would go a long way towards security, though it is not technically PHP specific.

Evert Pot

unread,
Sep 5, 2012, 1:09:48 PM9/5/12
to se...@googlegroups.com
On Sep 5, 2012, at 7:06 PM, Glendon Solsberry wrote:

> I've read a million different ways to "properly" hash a password. Most of the examples aren't very explanatory though. Can we create "the end all, be all" of explanations on how to properly hash a password (and how to store it, retrieve it, etc)?
>
> This would go a long way towards security, though it is not technically PHP specific.
>
> --

Use crypt() with a sensible workload (we use 7), and a per-password salt.

crypt($password, '$2y$07$' . $salt);

There is no be-all and end-all, but this should be the right way to do stuff for at least a few years ;)

Evert

Sky Gunning

unread,
Sep 5, 2012, 1:14:36 PM9/5/12
to se...@googlegroups.com

Hello
Where do toi store the user salt and the other key ?
Sky

--


Peter Lind

unread,
Sep 5, 2012, 1:20:35 PM9/5/12
to se...@googlegroups.com
The topic deserves a better description than that, as there are a ton
of pitfalls. To mention a few:
- password length must be 72 chars of less in blowfish
- your salt needs to be base64
- your salt should be of a decent quality

Not to mention that if Anthony Ferraras RFC gets implemented, things
might become somewhat simpler (see
https://wiki.php.net/rfc/password_hash).

Regards
Peter

--
<hype>
WWW: plphp.dk / plind.dk
CV: careers.stackoverflow.com/peterlind
LinkedIn: plind
Twitter: kafe15
</hype>

Glendon Solsberry

unread,
Sep 5, 2012, 1:31:02 PM9/5/12
to se...@googlegroups.com
On Wednesday, September 5, 2012 1:20:56 PM UTC-4, Peter Lind wrote:
The topic deserves a better description than that, as there are a ton
of pitfalls. To mention a few:
- password length must be 72 chars of less in blowfish
- your salt needs to be base64
- your salt should be of a decent quality

Not to mention that if Anthony Ferraras RFC gets implemented, things
might become somewhat simpler (see
https://wiki.php.net/rfc/password_hash).

Even that will take months/possibly years to be available everywhere.

Until then, what is the best method in current PHP 5.3 for creating secure password hashes? What about storing?

I know our codebase mostly just stores and md5sum, which I'd like to get away from. What's the proper way to do it?

Peter Lind

unread,
Sep 5, 2012, 1:37:28 PM9/5/12
to se...@googlegroups.com
Easiest/fastest and secure is using a library for it:
http://www.openwall.com/phpass/ or
https://github.com/ircmaxell/PHP-PasswordLib

Pádraic Brady

unread,
Sep 5, 2012, 1:47:42 PM9/5/12
to se...@googlegroups.com
I was just about to suggest looking into Anthony's library too. He's
sort of the resident expert in PHP in researching and highlighting
that area at the moment. He hasn't made it to this list just yet
(might need to send out the bloodhounds!).

Paddy
> --
>
>



--
Pádraic Brady

http://blog.astrumfutura.com
http://www.survivethedeepend.com
Zend Framework Community Review Team

Glendon Solsberry

unread,
Sep 5, 2012, 1:49:39 PM9/5/12
to se...@googlegroups.com
On Wed, Sep 5, 2012 at 1:37 PM, Peter Lind <peter....@gmail.com> wrote:
> Easiest/fastest and secure is using a library for it:
> http://www.openwall.com/phpass/ or
> https://github.com/ircmaxell/PHP-PasswordLib

That's good for creating the hashes and verifying. What about storage?

Pádraic Brady

unread,
Sep 5, 2012, 2:06:38 PM9/5/12
to se...@googlegroups.com
You might need to specify what you mean by storage? Obvious answer is
to store the password hash on the database.

Pádraic Brady

unread,
Sep 5, 2012, 2:07:50 PM9/5/12
to se...@googlegroups.com
Here's a slightly more in-depth tutorial.
http://sunnyis.me/blog/secure-passwords/

Paddy

Chris Cornutt

unread,
Sep 5, 2012, 2:11:38 PM9/5/12
to se...@googlegroups.com
It's pretty easy to come up with a session handler that uses encryption....I made something basic for Shield:

It still uses file-based session storage, but it gives you an idea.

-chris


--





--
Senior Editor
PHPDeveloper.org
ccor...@phpdeveloper.org
@enygma

Peter Lind

unread,
Sep 5, 2012, 2:13:38 PM9/5/12
to se...@googlegroups.com
With a normal password + salt scheme, you store them as you would any
data in your database. The output of both phpass and php-passwordlib
is a string specifying hashing algorithm, salt and hash - all of which
you just store normally as any other data in your database.

Regards
Peter

Peter Lind

unread,
Sep 6, 2012, 3:03:20 AM9/6/12
to se...@googlegroups.com
On 5 September 2012 20:07, Pádraic Brady <padrai...@gmail.com> wrote:
> Here's a slightly more in-depth tutorial.
> http://sunnyis.me/blog/secure-passwords/
>
> Paddy
>

I had a quick look at the tutorial and it contains some quite odd
info, it seems to me. Specifically:

// Passwords should never be longer than 72 characters to prevent DoS attacks
if (strlen($password) > 72) { die("Password must be 72 characters or less"); }

phpass uses crypt internally to hash with blowfish, if you don't use a
portable hash. When you hash long passwords with crypt using blowfish,
it looks like this:

<?php

$string0 = str_repeat('a', 71);
$string1 = str_repeat('a', 72);
$string2 = str_repeat('a', 73);
$salt = base64_encode('saltsaltsaltsalt');

// outputs $2a$12$c2FsdHNhbHRzYWx0c2Fsd.a9Quc5HIlkY/PQQC5zvUxS93pwHM8Km
echo crypt($string0, '$2a$12$' . $salt) . PHP_EOL;

// outputs $2a$12$c2FsdHNhbHRzYWx0c2Fsd.BRTZE5ipSuMcmxypumwDipO8f1ahMyG
echo crypt($string1, '$2a$12$' . $salt) . PHP_EOL;

// outputs $2a$12$c2FsdHNhbHRzYWx0c2Fsd.BRTZE5ipSuMcmxypumwDipO8f1ahMyG
echo crypt($string2, '$2a$12$' . $salt) . PHP_EOL;

Notice that crypt happily hashes all three strings - and,
problematically, hashes $string1 and $string2 to the same hash. The
actual problem of using long passwords with blowfish is that
information is thrown away - not a DoS exploit. Also, given the
comments, it seems the blog author doesn't quite know how crypt/phpass
works - suggesting that a longer password takes more cpu to hash,
which is not the case (same time spent hashing a 72 char password as a
7200000 char one). Digging through google, it seems this bit of info
actually comes from the author of phpass, which is odd ...

Anyway, this is all just in the way of saying: a better example would be good :)

Timo H

unread,
Sep 6, 2012, 5:51:16 AM9/6/12
to se...@googlegroups.com
Peter,

it is true that bcrypt does not use more than the 72 first characters of a password string. But the comment about DoS in that sunnyis.me blog post is taken out of the original context.

In the original article, there is a comment:
/* Don't let them spend more of our CPU time than we were willing to.
 * Besides, bcrypt happens to use the first 72 characters only anyway. */

In that original article, the password (and the corresponding username) are optionally piped to an external program which checks the quality of the password. So it is not just only about bcrypt.

I highly recommend to check out the original "How to manage a PHP application's users and passwords" article:
http://www.openwall.com/articles/PHP-Users-Passwords

Regards,
Timo

Peter Lind

unread,
Sep 6, 2012, 7:03:50 AM9/6/12
to se...@googlegroups.com
On 6 September 2012 11:51, Timo H <tim...@gmail.com> wrote:
> Peter,
>
> it is true that bcrypt does not use more than the 72 first characters of a
> password string. But the comment about DoS in that sunnyis.me blog post is
> taken out of the original context.
>
> In the original article, there is a comment:
> /* Don't let them spend more of our CPU time than we were willing to.
> * Besides, bcrypt happens to use the first 72 characters only anyway. */
>
> In that original article, the password (and the corresponding username) are
> optionally piped to an external program which checks the quality of the
> password. So it is not just only about bcrypt.

That's true. However, the DoS part has less to do with the optional
piping part than with the portable passwords, I belive. If you try to
create a hash with a very long string, using the portable method,
you'll notice a big delay, as it falls back to MD5'ing the input.

> I highly recommend to check out the original "How to manage a PHP
> application's users and passwords" article:
> http://www.openwall.com/articles/PHP-Users-Passwords
>

True, it's pretty good and explains a lot of the issues.
Reply all
Reply to author
Forward
0 new messages