Hacker News new | past | comments | ask | show | jobs | submit login

I wonder if Facebook stores it's password in clear-text, since you can login with either 'Password' or 'password', does it hash the first character and the rest into 2 different hashes? If not, we have a our passwords in readable form in their database that have huge privacy and security issues.

They hash it once and save it to the database. When logging in, they generate three hashes (if I remember correctly) and compare it to the hash in the database. If any match, it logs you in.

Edit: Here's a post on the matter http://www.zdnet.com/blog/facebook/facebook-passwords-are-no...

Facebook stores three hashes of your password (let's say it's "pAssword"):

* "pAssword" - the password as it is

* "PaSSWORD" - the password, case inverted, in case you have caps lock on

* "PAssword" - the password with its first letter capitalized, for those with mobile devices that insist on Capitalizing Everything.

I don't think they store three hashes, but just try to validate password with three hashes.

Something inline this: https://github.com/bungle/web.php/blob/master/password.php#L...

What's the password doing on their server?

Also, why is there no salt in the comparison. It calls a naked crypt, that whole ... interesting ... hash() function is sitting there unused.

I have serious doubts whether this code actually serves the user's interest - despite trying to be cute and helpful

You seemingly don't understand a bit about it. And you seemingly doesn't understand how crypt works. Let me educate you:

1. When user registers, his password is hashed with that hash-function, and that hash is stored in a database (it uses random salt).

2. When user tries to access the site, a password is hashed against the hash stored in a database, and it should return same hash if matched (this is how crypt works!).

3. In non strict mode we try also two different passwords to match the hashes (just like Facebook does).

Code example:

1. $hash = \password\hash('user entered password'); // store it to db

2. retrieve hash from db, and check it:

$valid = \password\check('user entered password', $hash, false);

3. // Now these passwords are valid:

'user entered password' // == correct form

'User entered password' // == Mobile browser capitalizing first char


And one line example:

$valid = \password\check('user entered password', \password\hash('user entered password'), false); // == true

Isn't that supposed to increase the chances of guessing the password? Unless there's a constraint on the number of attempts to guess the password, which I think there is.

By a factor of three, which is nothing.

Or they just make everything lower- or uppercase before checking it against the encrypted version.

Almost certainly not, since this would reduce the entropy of their passwords, making brute forcing easier.

It's more likely that they coerce to lowercase the the first letter of the password you put in and then store/compare the hash of that resulting plaintext. They could even transparently upgrade passwords created before they started doing this by using the plaintext from the next time you login successfully to regenerate the hash.

Lowercasing the first character--by itself alone--does not address inverted case scenario (e.g. "PaSsWoRd" and "pAsSwOrD" evaluate to "paSsWoRd" and "pAsSwOrD" respectively).

One way to resolve that issue is to create two versions of the password (one with normal casing and one with inverted casing, but both with the first character lowercased), sort them, and pick the first result.

    ["pAsSwOrD", "PaSsWoRd", "PAsSwOrD"].map(function canonicalize(pwd) {
        function invert(str) {
            return (str == str.toUpperCase()
                    ? str.toLowerCase()
                    : str.toUpperCase());
        var head = pwd.substring(0, 1).toLowerCase();
        var tail = pwd.substring(1);
        var vers = [head + tail,
                    head + tail.split("").map(invert).join("")];
        return vers.sort()[0];
Which gives the following result:

    ["pAsSwOrD", "pAsSwOrD", "pAsSwOrD"]
The three different variations get canonicalized into one version. With it, you can just store one hash instead of three.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact