Bcrypt elixir can´t verify the password if this was hashed in Yii2

I’m trying to migrate an old sistem that was made in the Php framework Yii2 to Phoenix, it has a long database of users registered, so i need to migrate the data user like the username and the password, and there it is the problem, the password from the old sistem is already hashed using Bcrypt from a function of Yii2, I’ve tried to test the login inserting a test user with his username and an yii2 hashed password in the new sistem database, but I can’t login in the new sistem and here it is the funny/strange thing:


The Bcrypt function throw me False, that’s why I can’t log in, but if I check in some other place if the password and the hash match the result is this:

Everywhere I check the password, it matches.
Even if I put a hashed password from phoenix in the old sistem and try to login, it works!

I got to say that im using “mix phx.gen.auth Accounts User users”

Yii2 hashing password code:

public function actionSignup()
        {
            $model = new User();
            if ($model->load(Yii::$app->request->post())) {
                if ($model->validate()) {
                    $login = new LoginForm();
                    $login->password = $model->password;
                    $login->username = $model->username;
                    $model->username = strtoupper($model->username);
                    $model->password = Yii::$app->getSecurity()->generatePasswordHash($model->password);

                    if($model->save() && $login->login()){
                        return $this->redirect(['login']);
                    }
                }
            }

            return $this->render('signup', [
                'model' => $model,
            ]);
        }

Phoenix password validation code:

def valid_password?(%Convocatorias.Accounts.User{hashed_password: hashed_password}, password)
      when is_binary(hashed_password) and byte_size(password) > 0 do
        Bcrypt.verify_pass(password, hashed_password)
  end

  def valid_password?(_, _) do
    Bcrypt.no_user_verify()
    false
  end

  @doc """
  Validates the current password otherwise adds an error to the changeset.
  """
  def validate_current_password(changeset, password) do
    if valid_password?(changeset.data, password) do
      changeset
    else
      add_error(changeset, :current_password, "is not valid")
    end
  end

1 Like

Hi,

as stated in its documentation, bcrypt_elixir does not support “$2y$” prefixed hashes:

The $2y$ prefix is not supported. For advice on how to use hashes with the $2y$ prefix, see this issue.

But replacing “$2y$” by “$2b$” should work (you can easily use pattern matching to rewrite it with an intermediate function as shown in the issue above, which should be safer than running a bulk UPDATE of user hashes)

2 Likes