Сохранение md5-хэша пароля в базе данных и его сравнение

#php #mysql #security

#php #mysql #Безопасность

Вопрос:

Перед вставкой данных в базу данных я зашифровал имя пользователя и пароль следующим образом:

  $userName=strip_tags($userName);
  $pass=strip_tags($pass);

  $userName= htmlentities($userName, ENT_QUOTES, 'UTF-8');
  $pass= htmlentities($pass, ENT_QUOTES, 'UTF-8');


  $userName=mysql_real_escape_string($userName);
  $pass=mysql_real_escape_string($pass);


   $salt = 'SHIFLETT';
   $password_hash = md5($salt . md5($pass.$salt));
  

Это было сделано для предотвращения SQL-атак и общих SQL-инъекций.

Теперь я хочу проверить пропуск и имя, которые пользователь дает мне при входе в систему. Я повторил тот же процесс экранирования удаления символов и экранирования специальных символов. Итак, вот моя функция для проверки прохождения:

    function validateLogin($user_name, $pass)
   {
  $userName=strip_tags($userName);
  $pass=strip_tags($pass);

  $userName= htmlentities($userName, ENT_QUOTES, 'UTF-8');
  $pass= htmlentities($pass, ENT_QUOTES, 'UTF-8');


  $userName=mysql_real_escape_string($userName);
  $pass=mysql_real_escape_string($pass);


   $salt = 'SHIFLETT';
   $password_hash = md5($salt . md5($pass.$salt));

   $result=mysql_query("SELECT COUNT(*) AS Result FROM users WHERE user_name='$user_name' AND pass='$password_hash'");

   mysql_close();

   if($row=mysql_fetch_array($result))
   {
       if($row['Result']>0)
       {
           echo "Login successful";
       }
       else
       {
           echo "Login unsuccessful";
       }
   }
   }
  

Мой вопрос заключается в том, будут ли работать проверки со всеми этими мерами безопасности? вернет ли MD5 тот же самый проход, если я использовал ту же кодировку MD5 для вставки, а затем для оператора select?

Комментарии:

1. md5 не является шифрованием.

2. Ваша соль должна быть уникальной для каждого пользователя и храниться в таблице вашей базы данных.

3. ну, злоумышленник не знает, что такое соль. соль должна быть каким-то дополнительным именем, «кодирующим» приложение .. не каждого отдельного пользователя

4. Использование соли помогает против предварительно вычисленных хэшей, другой хэш для каждого пользователя добавляет энтропии к вашим данным, больше энтропии = лучшая безопасность. Кроме того, md5 (или любой «быстрый» хэш) вреден для паролей, bcrypt — гораздо лучший вариант с точки зрения безопасности.

Ответ №1:

Для гибкости вам следует создать функцию для хэширования (а не шифрования) вашего пароля. Кроме того, используйте более сильный алгоритм, чем md5 (например, sha512, используемый в моем примере).

 function hashPassword($str)
{
        return hash("sha512", $str . "salt");
}
  

Я также рекомендую использовать mysql_real_escape_string .

 $password_hash = hashPassword($_POST['password']);
$username = mysql_real_escape_string($_POST['username']);
  

И вместо этого используйте auto_incremented int и выберите его.

 mysql> create table users (
-> id int primary key auto_increment,
-> username varchar(20),
-> password char(128)); 
  

Затем просто сравните возвращенную строку с именем пользователя и паролем.

 $check = "select id from users where username = '$username' and password = '$password_hash'";
$result = mysql_query($check);

if(mysql_num_rows($result))
{
    echo "<p>Login was successful!</p>n";
}
  

Чтобы ответить на ваш вопрос: да, сравнение хэшированного пароля с хэшированной строкой в базе данных будет работать.

Комментарии:

1. хотя SHA512 может быть «сильнее», чем MD5 в качестве хэша, на самом деле это не лучший вариант для хеширования паролей. Он должен быть «быстрым», что помогает «плохим людям», когда дело доходит до грубой силы …. посмотрите в «bcrypt»: en.wikipedia.org/wiki/Bcrypt

2. @Nico Спасибо за ввод, криптография на самом деле не моя сильная сторона. Я думаю, я, должно быть, пропустил это, но я думаю, это понятно, поскольку, похоже, в PHP нет официальной функции для bcrypt. Тем не менее, я рассмотрю это.

3. Я очень давно не касался PHP, но я предполагаю, что это то, с чего я бы начал: openwall.com/phpass

Ответ №2:

Короткий ответ: да, он будет соответствовать

Длинный / лекционный ответ: md5 слабый, постоянная соль плохая, нет необходимости экранировать пароль перед хешированием и т. Д.

Комментарии:

1. Также ВЫБЕРИТЕ пароль ОТ пользователя, ГДЕ username = ‘something’ LIMIT 1; а затем сравните пароль базы данных с заданным паролем.

2. Но есть только один пароль, который соответствует. нет необходимости в ограничении 1. потому что существует только одно уникальное имя пользователя и один пароль. итак, если оно равно 1, это означает, что пользователь существует. Я не вижу, какой предел 1 добавит

3. LIMIT 1 полезно, если у вас нет UNIQUE индекса для имени пользователя, поскольку он сообщает MySQL прекратить поиск после того, как он найдет один результат. В противном случае он продолжит обход таблицы.

Ответ №3:

 $pass=mysql_real_escape_string($pass);
  

довольно избыточно. Даже если пароль содержит метасимвол SQL (например, a ' ), он все равно исчезнет после того, как вы запустите пароль через md5. Все, что это сделало бы, это добавило дополнительный символ в строку пароля для каждого экранируемого символа, так что это было бы своего рода псевдосаливкой.

Но в остальном, да… до тех пор, пока вы выполняете один и тот же md5 / солевой процесс для паролей везде, где они используются, и сохраняете / сравниваете только полученный хэш в базе данных, тогда ваши сравнения будут действительными.

Ответ №4:

Этот вопрос несколько устарел, но теперь есть лучшие альтернативы с php 5.5. Приведенный выше код больше не нужен. Php 5.5 позволяет легко создавать встроенную защиту паролем. И это почти тупое доказательство. http://www.php.net/manual/en/function.password-hash.php Как вы можете видеть, просто используя

 password_hash("yourpass", PASSWORD_DEFAULT)
  

Вы используете как случайную соль, так и bcrypt одновременно. Если вы не обновились до последних версий php, я бы посоветовал сделать это сейчас.