Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using MD5 in symfony2 security.yml for legacy users

Tags:

php

hash

symfony

I have a legacy system which contains md5 hashed passwords. I have tested these to be correct and they do not use a salt.

security.yml

security:
    encoders:
        Namespace\MyBundle\Entity\User:
            algorithm: md5
providers:
    entityUsers:
        entity: { class: NamespaceBundle:User, property: username }

In my User entity I have implemented UserInterface and made sure the salt is set to the empty string.

But I get a bad credentials error when trying to authenticate.

I have tried switching security.yml to plaintext and entered the hash and the system works fine.

Surely md5 should just work?

like image 337
Jon Winstanley Avatar asked Sep 11 '13 10:09

Jon Winstanley


2 Answers

I was having exactly the same problem and had to dig into the code to find out why.

You don't need to create a custom encoder.

By default, the MessageDigestPasswordEncoder encoder (Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder) in Symfony 2.5 - and possibly all Symfony 2 releases - calculates the MD5 hash of the raw password, with/without using a salt, as expected, and then re-hashes the MD5 a number of times (5000 times, by default, in Symfony 2.5). To make things that little bit more exciting, the encoder will also base64-encode the hash, by default. Both of those features were causing problems for me.

You can fix the problem(s) by disabling the re-hashing and/or disabling the base64 encoding, in security.yml, thus:

security:
    encoders:
        Namespace\Of\Your\User: 
            algorithm: md5
            encode_as_base64: false
            iterations: 0

Hope that saves you some time.

like image 162
Dan B Avatar answered Oct 17 '22 06:10

Dan B


Turns out that the md5 in symfony2 uses a salt by default. There may be an easier way, but I just created a custom md5 password encoder interface that ignores salt.

Register a service

namespace.project.md5password.encoder:
    class: Namepspace\MyBundle\Services\CustomMd5PasswordEncoder

Create the encoder service

namespace Namespace\MyBundle\Services;

use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;

class CustomMd5PasswordEncoder implements PasswordEncoderInterface
{
    public function __construct() {
    }

    public function encodePassword($raw, $salt) {
        return md5($raw);
    }

    public function isPasswordValid($encoded, $raw, $salt) {
        return md5($raw) == $encoded;
    }
}

Use the new service in security.yml

security:
    encoders:
        Namespace\MyBundle\Entity\User:
            id: namespace.project.md5password.encoder

Hope this helps

like image 21
Jon Winstanley Avatar answered Oct 17 '22 05:10

Jon Winstanley