【问题标题】:Storing md5 hash of a password in database and comparing it将密码的 md5 哈希存储在数据库中并进行比较
【发布时间】:2011-10-18 15:07:24
【问题描述】:

在向数据库插入数据之前,我将用户名和密码加密如下:

 $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 会返回相同的传递吗?

【问题讨论】:

  • md5 不是加密。
  • 您的 salt 对于每个用户都应该是唯一的,并存储在您的数据库表中。
  • 好吧,攻击者不知道什么是盐。盐应该是一些额外的名称“编码”应用程序..不是每个单独的用户
  • 使用盐有助于对抗预先计算的哈希,每个用户的不同哈希会为您的数据增加熵,更多的熵 = 更好的安全性。此外,md5(或任何“快速”哈希)对密码不利,bcrypt 是一个更好的选择,安全方面。

标签: php mysql security


【解决方案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";
}

回答您的问题:是的,将散列密码与数据库中的散列字符串进行比较即可。

【讨论】:

  • 虽然 SHA512 作为哈希值可能比 MD5 “更强”,但它并不是哈希密码的更好选择。它旨在“快速”,在暴力破解时帮助“坏人”....查看“bcrypt”:en.wikipedia.org/wiki/Bcrypt
  • @Nico 感谢您的输入,密码学并不是我的强项。我想我一定是错过了它,但我想这是可以理解的,因为 PHP 中似乎没有 bcrypt 的官方函数。不过,我会调查一下。
  • 我已经很久没有接触 PHP 了,但我猜这就是我要开始的地方:openwall.com/phpass
【解决方案2】:

简短回答:是的,它会匹配

长篇/讲座回答:md5 很弱,常量盐很差,不需要在散列之前转义密码等。

【讨论】:

  • 也从用户那里选择密码 WHERE username = 'something' LIMIT 1;然后将数据库密码与给定密码进行比较。
  • 但是只有一个密码匹配。不需要限制 1. 因为只有一个唯一的用户名和一个密码。所以如果为1,则表示用户存在。我看不到限制 1 会添加什么
  • LIMIT 1 在用户名上没有UNIQUE 索引时会很有帮助,因为它告诉 MySQL 在找到单个结果后停止查找。否则它将继续遍历表。
【解决方案3】:
$pass=mysql_real_escape_string($pass);

是相当多余的。即使密码包含 SQL 元字符(例如 '),在您通过 md5 运行密码后它仍然会消失。所有这一切都会为每个可转义的字符在密码字符串中添加一个额外的字符,所以它是一种伪加盐。

但除此之外,是的...只要您在使用密码的所有地方都对密码执行完全相同的 md5/salting 过程,并且只在数据库中存储/比较结果哈希,那么您的比较将是有效的。

【讨论】:

    【解决方案4】:

    这个问题有点老了,但是现在 php 5.5 有更好的选择。不再需要上面的代码。 PHP 5.5 允许轻松创建内置的密码保护。而且它几乎是愚蠢的证明。 http://www.php.net/manual/en/function.password-hash.php 如您所见,仅使用

    password_hash("yourpass", PASSWORD_DEFAULT)
    

    您同时使用随机盐和 bcrypt。如果您还没有更新到最新版本的 php,我建议您现在就这样做。

    【讨论】:

      猜你喜欢
      • 2015-08-15
      • 2017-08-05
      • 2016-03-06
      • 1970-01-01
      • 2021-10-23
      • 1970-01-01
      • 1970-01-01
      • 2012-11-25
      • 1970-01-01
      相关资源
      最近更新 更多