Verifying MD5 passwords using password_verify()

12,554

You can't do that.

What you can do is to hash the already MD5-hashed passwords via password_hash() and put an additional flag for these old passwords in your database, so you know to double-verify them afterwards.

Some sample code:

$passwordCompare = ($passwordIsOldFlag === true)
    ? md5($passwordInput)
    : $passwordInput;

if (password_verify($passwordCompare, $passwordHash))
{
    if ($passwordisOldFlag === true)
    {
        $passwordNewHash = password_hash($passwordInput, PASSWORD_DEFAULT);

        // Here, you'd update the database with the new, purely bcrypt hash
        // and set your passwordIsOldFlag to 0 as well
    }
}

Note: MD5 produces a 32 character length string, while password_hash() is a minimum of 60.

Read the manual:

If and when you do decide to use password_hash() or the compatibility pack (if PHP < 5.5) https://github.com/ircmaxell/password_compat/, it is important to note that if your present password column's length is anything lower than 60, it will need to be changed to that (or higher). The manual suggests a length of 255.

You will need to ALTER your column's length and start over with a new hash in order for it to take effect. Otherwise, MySQL will fail silently.

Share:
12,554
Magnar Myrtveit
Author by

Magnar Myrtveit

SOreadytohelp

Updated on June 26, 2022

Comments

  • Magnar Myrtveit
    Magnar Myrtveit almost 2 years

    Is there a way to convert a MD5 password to something that can be verified by password_verify()?

    I read on the Crypt Wikipedia page that "The printable form of MD5 password hashes starts with $1$."

    Hence I give this a shot (without any luck):

    $password = "abcd1234";
    $md5hash = "$1$".md5($password);
    var_dump(password_verify($password, $md5hash));
    

    Is there any way to make password_verify() work with MD5 passwords?

    Reason for question: I have an old system where the passwords are stored as MD5 hashes. I want to start using the more secure Password Hashing API. If I'm able to convert the existing password hashes to something that works with password_verify(), I can just update the database entries (prepend $1$ to all password hashes), and my program would work beautifully using the following code (I don't have to make a special case for the old MD5 passwords):

    $password; // Provided by user when trying to log in
    $hash; // Loaded from database based on username provided by user
    if(password_verify($password, $hash)) {
       // The following lines will both update the MD5 passwords
       // and all passwords whenever the default hashing algorithm is updated
       if(password_needs_rehash($hash, PASSWORD_DEFAULT)) {
          $hash = password_hash($password, PASSWORD_DEFAULT);
          // Store the new hash in database
       }
       // User is logged in
    } else {
       // User is not logged in
    }