Помогите загнать в БД пароль в md5!

Общие вопросы по использованию фреймворка. Если не знаете как что-то сделать и это про Yii, вам сюда.
ynik
Сообщения: 124
Зарегистрирован: 2010.05.05, 13:07
Откуда: Ukraine

Помогите загнать в БД пароль в md5!

Сообщение ynik »

Доброго времени суток!
Сижу парюсь целый день и немогу понять как при регистрации нового юзера пароль и salt занести в базу в md5.
поскольку я понял за мой невеликий опыт работы с этим чудесным фреймворком аж пару дней, что по примеру в демо блоге такой подход что password.salt в БД зашифрован через md5 и занесен в БД как вместе сгенерирован типа md5($salt.$password);, так а само поле salt (так понял секретное слово в помощь еще большей безопасности шифровки пароля) кодируеться отдельно и записываеться в БД. исходя из этого я
Прописываю в контроллере следующее:

Код: Выделить всё

public function actionCreate()
        {
                $model=new User;
                // collect user input data
                if(isset($_POST['User']))
                {
                        $model->attributes=$_POST['User']; // set all attributes with post values
 
                        // validate user input and redirect to previous page if valid
                        if($model->validate())
                        {        
                                                    /*
                                                   здесь перед сейвом после успешной валидации перехвачиваю $model->password,$model->salt  и   шифрую. Функция: public function hashPassword($password,$salt)
    {
        return md5($salt.$password);
    }
                                                    */
                                                                $model->salt =    md5($model->$salt);            
                                 $model->password = User::hashPassword($model->password,$model->salt);
                                $model->save();
                                                                $this->redirect(array('view','id'=>$model->id));     
                        }     
                }
    
                $this->render('create',array('model'=>$model));
        } 
и сейв не срабатывает и мой редирект не 404 соответсвенно, как запись не создана и id не существует, без моих шифровок функция работает и в базу все летит только в незашифрованном виде. Та и в конце концов можно уже сам пароль шифровать только, без salt что тоже не выходит.
Что не так я делаю, где ошибка, если я туплю по полной в моем случае, поставьте плиз на путь истинный.
Последний раз редактировалось ynik 2010.05.10, 09:28, всего редактировалось 1 раз.
Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Помогите загнать в БД пароль в md5!

Сообщение timlar »

Я когда начинал изучать, смотрел пример демо блога, там есть то, чего не указано в руководстве. Советую посмотреть код.

А вообще, меня эта идея с солью не вдохновила. Юзаю следующий алгоритм шифрования пароля:

Код: Выделить всё

    protected function beforeSave()
    {
        if($this->isNewRecord)
            $this->password = Users::hash($this->password);

        return true;
    }

    public function hash($password)
    {
        return base64_encode(pack('H*', sha1((trim($password)))));
    } 
Twitter: @timlar_ua
ynik
Сообщения: 124
Зарегистрирован: 2010.05.05, 13:07
Откуда: Ukraine

Re: Помогите загнать в БД пароль в md5!

Сообщение ynik »

Timlar спасибо за Ваш вариант шифровки! применяя beforeSave функцию все получилось, только интересно почему с солью вариант не самый лутший? можно закодировать с солью в md5 и еще раз загнать в SHA1
Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Помогите загнать в БД пароль в md5!

Сообщение timlar »

С солением вариант тоже не плохой, и вполне рабочий, но мне удобнее так, как я написал :)
Twitter: @timlar_ua
Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Помогите загнать в БД пароль в md5!

Сообщение timlar »

Опишу свой вариант с солью:

В модели Users:

Код: Выделить всё

    // После валидации присваиваем пароль, соль и роль.
    public function afterValidate()
    {
        if($this->isNewRecord) {
            $salt = self::randomSalt();
            $this->password = self::hashPassword($this->password, $salt);
            $this->salt = $salt;
            $this->role = 'user';
        }
        return true;
    }

    // Проверка валидности пароля
    public function validatePassword($password)
    {
        return $this->hashPassword($password,$this->salt)===$this->password;
    }

    // Создание хэша пароля
    public function hashPassword($password,$salt)
    {
        return md5($salt.$password);
    }

    // Генерация "соли". Этот метод генерирует случайным образом слово
    // заданной длины. Длина указывается в единственном свойстве метода.
    // Символы, применяемые при генерации, указаны в переменной $chars.
    // По умолчанию, длина соли 32 символа.
    public function randomSalt($length=32)
    {
        $chars = "abcdefghijkmnopqrstuvwxyz023456789";
        srand((double)microtime()*1000000);
        $i = 1;
        $salt = '' ;

        while ($i <= $length)
        {
            $num = rand() % 33;
            $tmp = substr($chars, $num, 1);
            $salt .= $tmp;
            $i++;
        }
        return $salt;
    } 
Ну, и собственно компонент UserIdentity:

Код: Выделить всё

class UserIdentity extends CUserIdentity
{
    protected $_id;

    public function authenticate()
    {
        $user = User::model()->find('LOWER(username)=?', array(strtolower($this->username)));
        if($user === null) {
            $this->errorCode = self::ERROR_USERNAME_INVALID;
        } elseif(User::hashPassword($this->password, $user->salt) !== $user->password) {
            $this->errorCode = self::ERROR_PASSWORD_INVALID;
        } else {
            $this->_id = $user->id;
            $this->errorCode = self::ERROR_NONE;
        }
        return !$this->errorCode;
    }

    public function getId()
    {
        return $this->_id;
    }

} 
Twitter: @timlar_ua
ynik
Сообщения: 124
Зарегистрирован: 2010.05.05, 13:07
Откуда: Ukraine

Re: Помогите загнать в БД пароль в md5!

Сообщение ynik »

Timlar Спасибо! Интересное решение с генерацией случайного слова!
А я от так решил

Код: Выделить всё

public function beforeSave()
    {
        // hash password for database.
        $pass = sha1(md5($this->password).Yii::app()->params["salt"]);
          $this->password = $pass;
          return true;
    } 
Соль в конфиге задаю , одно на все пароли.
только чтоб востановить такие пароли, наверно неполучится придется новий генерить...
Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Помогите загнать в БД пароль в md5!

Сообщение timlar »

Это не верно. Принцип соления как раз в том, чтобы у каждого юзера была своя соль. А если делать одну на всех, то в этом нет абсолютно никакого смысла.

На счет восстановления... А ты как-то можешь восстановить пароль из обычного мд5 хэша? Я что-то пропустил? :)
Twitter: @timlar_ua
ynik
Сообщения: 124
Зарегистрирован: 2010.05.05, 13:07
Откуда: Ukraine

Re: Помогите загнать в БД пароль в md5!

Сообщение ynik »

Это не верно. Принцип соления как раз в том, чтобы у каждого юзера была своя соль.
Та уже понял что неправильный подход, так что думаю Ваш вариант случайного слова лутше, чем заставлять юзера вводить соль.
а на счет вотсановленияБ я имею ввиду если делать опцию для юзера востановления пароля то тут уже не проканает старый пароль на почту, нужно новый генерить пароль с солью, и отсылать тогда. :?
Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Помогите загнать в БД пароль в md5!

Сообщение timlar »

Пользователь не должен вводить соль. Он вообще не должен знать о том, как и что там в тебя генерируется.

Алгоритмов восстановления пароля много. Наиболее легкий вариант, это при восстановлении, генерировать новый пароль и отправлять пользователю на почту. Но его неудобство в том, что кто-то случайно (или специально) может нажать на восстановление пароля и пароль изменится. Потом пользователю придется заходить под новым паролем и менять его в своем профайле. Чтобы этого избежать, можно делать различные проверки, например, присылать пользователю письмо с уведомлением, что кто-то попытался восстановить пароль, если это Вы, то пройдите по такой-то ссылки. И лишь пройдя по ссылке пароль либо меняется и отправляется новый на почту, либо предоставляется пользователю ввести сразу новый пароль. Тут уже личные предпочтения каждого, как реализовывать данный функционал. :)
Twitter: @timlar_ua
AbS_
Сообщения: 207
Зарегистрирован: 2010.03.27, 14:02

Re: Помогите загнать в БД пароль в md5!

Сообщение AbS_ »

Timlar писал(а):Опишу свой вариант с солью:

В модели Users:

Код: Выделить всё

    // После валидации присваиваем пароль, соль и роль.
    public function afterValidate()
    {
        if($this->isNewRecord) {
            $salt = self::randomSalt();
            $this->password = self::hashPassword($this->password, $salt);
            $this->salt = $salt;
            $this->role = 'user';
        }
        return true;
    }

    // Проверка валидности пароля
    public function validatePassword($password)
    {
        return $this->hashPassword($password,$this->salt)===$this->password;
    }

    // Создание хэша пароля
    public function hashPassword($password,$salt)
    {
        return md5($salt.$password);
    }

    // Генерация "соли". Этот метод генерирует случайным образом слово
    // заданной длины. Длина указывается в единственном свойстве метода.
    // Символы, применяемые при генерации, указаны в переменной $chars.
    // По умолчанию, длина соли 32 символа.
    public function randomSalt($length=32)
    {
        $chars = "abcdefghijkmnopqrstuvwxyz023456789";
        srand((double)microtime()*1000000);
        $i = 1;
        $salt = '' ;

        while ($i <= $length)
        {
            $num = rand() % 33;
            $tmp = substr($chars, $num, 1);
            $salt .= $tmp;
            $i++;
        }
        return $salt;
    } 
Ну, и собственно компонент UserIdentity:

Код: Выделить всё

class UserIdentity extends CUserIdentity
{
    protected $_id;

    public function authenticate()
    {
        $user = User::model()->find('LOWER(username)=?', array(strtolower($this->username)));
        if($user === null) {
            $this->errorCode = self::ERROR_USERNAME_INVALID;
        } elseif(User::hashPassword($this->password, $user->salt) !== $user->password) {
            $this->errorCode = self::ERROR_PASSWORD_INVALID;
        } else {
            $this->_id = $user->id;
            $this->errorCode = self::ERROR_NONE;
        }
        return !$this->errorCode;
    }

    public function getId()
    {
        return $this->_id;
    }

} 
На сколько я понял то соль храниться в модели пользователя?
В таком случае, что помешает расшифровать хешь пароля и вычесть из него соль, получить пароль?
Аватара пользователя
IceDragon
Сообщения: 50
Зарегистрирован: 2010.04.08, 20:02

Re: Помогите загнать в БД пароль в md5!

Сообщение IceDragon »

а) у каждого пользователя своя соль
б) эта соль не передается никак внешне
в) даже если взять хеш - исчезающе мала вероятность что райнбоу таблицы или другие методы подберут пароль.соль в качестве входных параметров.

т.е. фактически добиваемся усложнения строки хеша путем рандомизации одного параметра и удлинения строки
AbS_
Сообщения: 207
Зарегистрирован: 2010.03.27, 14:02

Re: Помогите загнать в БД пароль в md5!

Сообщение AbS_ »

Ну в данном алгоритме идет: соль+пароль
далее:
1) воруем базу.
2) дешефруем пароль.
3) вычитаем соль.
Я не вижу тут больших преимуществ.

Вот если соль использовать как один из ключей шифрования пароля перед его зашифровкой в мд5, то мы получим некую бяку, даже после расшифровки. А просто пароль + соль, мало эффективны, если и пароль и соль в одной БД, то Получив доступ к базе, расшифровать все не составит труда.
Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Помогите загнать в БД пароль в md5!

Сообщение timlar »

AbS_ писал(а):Ну в данном алгоритме идет: соль+пароль
далее:
1) воруем базу.
2) дешефруем пароль.
3) вычитаем соль.
Я не вижу тут больших преимуществ.

Вот если соль использовать как один из ключей шифрования пароля перед его зашифровкой в мд5, то мы получим некую бяку, даже после расшифровки. А просто пароль + соль, мало эффективны, если и пароль и соль в одной БД, то Получив доступ к базе, расшифровать все не составит труда.
Можно подробнее о втором пункте? ;) С примерами, конечно же... ;) Очень хочется на это посмотреть...
Twitter: @timlar_ua
zarafar
Сообщения: 39
Зарегистрирован: 2010.04.04, 10:48

Re: Помогите загнать в БД пароль в md5!

Сообщение zarafar »

AbS_ писал(а):2) дешефруем пароль.
Имеется ввиду, что если пользователь ввел пароль 123, то подобрать пароль к хешу не составит труда.
Если к такому паролю добавить соль например "asf1FG34", то подобрать пароль к хешу получившейся строки "123asf1FG34" гораздо сложнее. Возможно, но затратно.

Соль - усиление слабых паролей. Но мы не можем определить на сколько хорош введёный пользователем пароль, поэтому солим все пароли, это нам не сильно накладно. :)
AbS_
Сообщения: 207
Зарегистрирован: 2010.03.27, 14:02

Re: Помогите загнать в БД пароль в md5!

Сообщение AbS_ »

Я про то что.
Имеем хешь:
827ccb0eea8a706c4c34a16891f84e7b
идем сюда: http://md5.rednoize.com/
получаем: 12345

А как поможет в такой ситуации соль?
Ну получим мы 12345<соль>, но в таблице у нас есть соль. Вычитаем соль и получаем пароль. Разве нет?
zarafar
Сообщения: 39
Зарегистрирован: 2010.04.04, 10:48

Re: Помогите загнать в БД пароль в md5!

Сообщение zarafar »

AbS_ писал(а):Я про то что.
Имеем хешь:
827ccb0eea8a706c4c34a16891f84e7b
идем сюда: http://md5.rednoize.com/
получаем: 12345
Так и есть, для этого и нужна соль.
AbS_ писал(а): А как поможет в такой ситуации соль?
Ну получим мы 12345<соль>, но в таблице у нас есть соль. Вычитаем соль и получаем пароль. Разве нет?
md5(12345<соль>) вставляем на тот же сайт и ничего не находим. Соль мы можем вычесть, если уже подобрали исходную строку. Если у нас только хеш, мы не можем из него вычесть соль.
Аватара пользователя
timlar
Сообщения: 1382
Зарегистрирован: 2009.09.19, 17:49
Откуда: Украина, Днепропетровск
Контактная информация:

Re: Помогите загнать в БД пароль в md5!

Сообщение timlar »

Twitter: @timlar_ua
zarafar
Сообщения: 39
Зарегистрирован: 2010.04.04, 10:48

Re: Помогите загнать в БД пароль в md5!

Сообщение zarafar »

Можно еще так sha1(md5($pass).md5($salt)), при сколь угодно слабых $pass и $salt исходная строка для sha1 получается достаточно большая. Но вычислять такой хеш уже накладно каждый раз.

Кстати хэш = соль + md5(соль+пароль) , хороший вариант из расчета скорость\стойкость. Достаточно тяжелый md5 используется 1 раз + взломщику нужно знать алгоритм шифрования.
AbS_
Сообщения: 207
Зарегистрирован: 2010.03.27, 14:02

Re: Помогите загнать в БД пароль в md5!

Сообщение AbS_ »

А по мне так, если взломщик получил дамб базы, то все остальное уже не имеет значения. :)
zarafar
Сообщения: 39
Зарегистрирован: 2010.04.04, 10:48

Re: Помогите загнать в БД пароль в md5!

Сообщение zarafar »

AbS_ писал(а):А по мне так, если взломщик получил дамб базы, то все остальное уже не имеет значения. :)
Интересная позиция :) Если например взломщик получил дамп базы финансовой структуры, он сможет только посмотреть состояние счетов, ну увидит он что у Васи Пупкина 1 лям на счету. А что дальше ? А дальше ничего. Позавидует.

А если взломщик из этого же дампа узнает еще и данные доступа к системе? У Васи станет на 1 лям меньше, а у взломщика на 1 лям больше.
Ответить