Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jago86's avatar
Level 19

MD5 to Laravel passwords

Hi, I have a database with users and passwords encrypted in md5. I wanna let the users login with their passwords, but after they are logged in, change the md5 to the Laravel encryption way. Any suggestions?

0 likes
12 replies
DarkRoast's avatar

You can't convert an MD5 to a bcrypt but after they successfully log in you could run their plaintext password through the bcrypt() function that comes with Laravel and store that.

DarkRoast's avatar

I usually set a mutator on my users model:

    public function setPasswordAttribute($value)
    {
        $this->attributes['password'] = bcrypt($value);
    }
martinbean's avatar

@jago86 You’ll need two password columns: one containing the current MD5 hash, and a nullable column for bcrypt-hashed passwords.

On login, fetch the user by the username or email address. If their bcrypt password column is null, hash their password and compare it to their existing MD5 hash. If it matches, run the raw, POSTed password value through bcrypt and then save that value to the database.

2 likes
Snapey's avatar
Snapey
Best Answer
Level 122

As @martinbean says, but then delete the MD5 password (after thoroughly testing!) since you make the whole exercise pointless if you leave the old MD5 passwords around. (http://fortune.com/2015/09/11/ashley-madison-passwords/)

You can put the logic in the AuthController. Search for the trait AuthenticatesUsers.php and replace any of the trait functions in your App/Auth/AuthController and don't be tempted to alter the code in the vendor folder.

mtpultz's avatar

Though having two columns one old and one new to update the passwords seems workable. It is better to apply a meta-algorithm so you only need your existing password column.

  1. Apply bcrypt to all the users passwords in the database by wrapping the md5 passwords in bcrypt as if they are plain-text
  2. When a user attempts to authenticate use bcrypt alone, and if authentication fails then double encrypt with md5 then bcrypt and re-authenticate
  3. Once authenticated store the password using just bcrypt so the double encryption doesn't have to be applied twice to the same user.

Like @Snapey says you can do this all by pulling up the AuthenticatesUsers::login method into AuthController and apply your own custom attempt after Laravel makes the first attempt.

I read about this at https://medium.com/@uther_bendragon/sustainable-password-hashing-8c6bd5de3844#.sa9assa8k

1 like
morgano's avatar

This is slightly late but might help anyone else with the same problem. The simplest solution is to add a mutator like @DarkRoast suggested, then on login check if user updated_at > launch date of your new site such as:

Here's my code:

    public function verify($username, $password)
    {
        $user = $this->user->where('email', strtolower($username))->first();

        if (strtotime($user->updated_at) > strtotime("06/20/2016")) 
        {
            if (app('hash')->check($password, $user->getAuthPassword())) 
            {
                return $user->getKey();
                
            }           
        } else {
            if (md5($password) == $user->password) 
            {
                $user->password = $password;
                $user->save();
                
                return $user->getKey();
            }
        }
        return false;
    }

Basically, you only need 1 column for the password to store both the new and old passwords. When older users login it will automatically authenticate them, update the password and next time they login it will authenticate them correctly with the new hash.

1 like
Snapey's avatar

@morgano

Basically, you only need 1 column for the password to store both the new and old passwords. When older users login it will automatically authenticate them, update the password and next time they login it will authenticate them correctly with the new hash.

Assuming you remember to make the password column wide enough for the new hash length

1 like
badershs's avatar

what i did is bcrypt all the md5 passwords inside my database Then when the user try to login in I pass the md5 of his input (password) but actually you have to extend the time out of your server when you try to bcrypt all the password from your database because it took along time to bcrypt them ( near to half an hour for each 2000 password ) i really dont know why ,

jlrdw's avatar

I am surprised anyone still has a database with md5, it's been crackable a while now, wow.

Snapey's avatar

it took along time to bcrypt them ( near to half an hour for each 2000 password ) i really dont know why

@badershs its designed to be a long process to slow down brute force attacks. A good implementation will use a number of iterations of the algorithm just to make it take longer.

haldorsen's avatar

How would you do this in Laravel 5.4? I wanted to try the approach @morgano is using, but I don't know how to make Laravel use it instead of it's own password check. What controller should I put it in, and what should I name the method?

Please or to participate in this conversation.