8

I am working on an old php app and the password of the users are hashed with the md5() function. So the passwords are stored like:

c0c92dd7cc524a1eb55ffeb8311dd73f

I am developing a new app with Laravel 4 and I need suggestions on how to migrate the users table without losing the password field.

Mehravish Temkar
  • 4,275
  • 3
  • 25
  • 44
cawecoy
  • 2,359
  • 4
  • 27
  • 36
  • 7
    Lose the password field. You shouldn't continue to use md5, and there's no realistic way to reverse the md5 to plain text, just to rehash again with Laravel's bcrypt. I would implement Laravel's password reset/reminder feature on your site, then do a foreach and set each users's password to a random one. Then send an email to all your users asking them to reset their password. Then you can completely use Laravel properly and securely. – Sajan Parikh Nov 13 '13 at 14:07

1 Answers1

18

Lose the password field as fast as you can, but if you don't want risking to lose users, you can do something like this on your auth method:

if (Auth::attempt(array('email' => Input::get('email'), 'password' => Input::get('password'))))
{
    return Redirect::intended('dashboard');
}
else
{
    $user = User::where('email', Input::get('email'))->first();

    if( $user && $user->password == md5(Input::get('password')) )
    {
        $user->password = Hash::make(Input::get('password'));

        $user->save();

        Auth::login($user->email);

        return Redirect::intended('dashboard');
    }

}

This will basically change a password from md5 to Hash every time a user logs in.

But you really have to think about sendind a link to all your users so they change their passwords.

EDIT:

To improve security even more, according to @martinstoeckli comment, would be better to:

Hash all your current md5 passwords:

foreach(Users::all() as $user)
{
    $user->password = Hash::make($user->password);

    $user->save();
}

And then use an even more cleaner method to update your passwords:

$password = Input::get('password');
$email = Input::get('email');

if (Auth::attempt(array('email' => $email, 'password' => $password)))
{
    return Redirect::intended('dashboard');
}
else
if (Auth::attempt(array('email' => $email, 'password' => md5($password))))
{
    Auth::user()->password = Hash::make($password);

    Auth::user()->save();

    return Redirect::intended('dashboard');
}
Mehravish Temkar
  • 4,275
  • 3
  • 25
  • 44
Antonio Carlos Ribeiro
  • 86,191
  • 22
  • 213
  • 204
  • So basically retain old password hash and on first successful login rehash and update db? What would be the recommended retention period before phasing this out? Couldn't the old hash values be rehashed to the stronger algorithm and then the input double hashed (with some flag indicating when necessary?) – Anthony Nov 13 '13 at 15:01
  • 1
    Yes. Still not really secure, but better than keep them forever on md5, since you cannot just convert them. – Antonio Carlos Ribeiro Nov 13 '13 at 15:03
  • 1
    @Anthony - It is ok to hash the unsafe MD5 values with BCrypt, to give immediate protection. In this [answer](http://stackoverflow.com/a/14402451/575765) i tried to show the procedure. The biggest problem with MD5 is its speed, BCrypt will slow it down. Of course you should replace the hash after a successful login anyway. – martinstoeckli Nov 13 '13 at 20:30
  • Nice post and ideas about security. Just updated mine to add yours. Thanks. – Antonio Carlos Ribeiro Nov 13 '13 at 20:48
  • Great logic as I was trying to do the same but rather than doing your way I was changing the complete system so that it takes only the md5 hash and decided to compromise security but with your solution I managed to save that hashing security +1 for this piece of code. – Mohsin Abbas Jun 21 '18 at 12:12