Search code examples
phpmysqlpasswordscryptpassword-confirmation

When checking password, it only cares about the first 8 characters


I have a sign-up form that creates a profile and an "Edit Profile" page that allows the user to change information as long as they also enter their password.

The problem is that the "Edit Profile" page only makes sure that the first 8 characters of the password match. Or, actually, I guess a better description would be that the crypt() function is only encoding the first 8 characters.

Here is my code for the sign-up form:

    $password = $_REQUEST['password'];

    // Checks to make sure that the password isn't blank
    if (!$password) {
          handle_error("You have left the password field blank.", "Blank Password"); 
    //handle_error() is a custom function
    }

And here is my code for inserting this into the MySQL database:

    $insert_sql = sprintf("INSERT INTO users (first_name, last_name, pen_name, website, password, email, user_bio, user_reason, hash, profile_pic) " .
            "VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s');",
            mysql_real_escape_string($first_name),
            mysql_real_escape_string($last_name),
            mysql_real_escape_string($pen_name),
            mysql_real_escape_string($website),
            mysql_real_escape_string(crypt($password, $email)),
            mysql_real_escape_string($email),
            mysql_real_escape_string($bio), 
            mysql_real_escape_string($reason), 
            mysql_real_escape_string($hash), 
            mysql_real_escape_string($upload_filename));

The purpose of the "hash" variable has nothing to do with the password, so ignore that.

And here's the code for the "Edit Profile" code.

    $password_query = "SELECT * FROM users WHERE user_id = " . $user_id;    
            $password_query_run = mysql_query($password_query); 
            $password_array = mysql_fetch_array($password_query_run);   
            $password_old_hash = $password_array['password'];   
            $password_new_hash = crypt($password, $email);  
            if(!($password_new_hash === $password_old_hash)) {
                    handle_error("The Password you entered does match what we have in our system.","Wrong Password.");
            }

I'm relatively new to PHP, but I did write all of that code myself, so if anyone needs any clarification, I'll happily explain myself.

As I've said, the problem is that my pages only care about the first 8 characters of the password. When I try to verify on "Edit Profile" with the wrong password, it gives an error. If I leave the password blank, it gives an error. But if I type in the first 8 characters correctly and then a bunch of gibberish, it accepts the password! I'm not sure if there's some function of crypt() or strings that I don't get.

Oh, and I am doing (!($string1 === $string2)), but I have tried the strcomp() function and that worked the same way.

Thanks so much!


Solution

  • From: http://php.net/manual/en/function.crypt.php

    The standard DES-based crypt() returns the salt as the first two characters of the output. It also only uses the first eight characters of str, so longer strings that start with the same eight characters will generate the same result (when the same salt is used).

    You should try another algorithm in order to get the hash. You can find differents examples in the link.

    Wish it helps!