【问题标题】:How do I create and store md5 passwords in mysql如何在 mysql 中创建和存储 md5 密码
【发布时间】:2011-10-10 13:10:56
【问题描述】:

可能是一个非常新手的问题,但是,我一直在阅读并发现在理解密码的创建和存储方面有些困难。从我读过的内容来看,md5/hash 密码是将它们存储在数据库中的最佳方式。但是,我将如何首先创建这些密码?

假设我有一个用户 bob 和密码 bob123 的登录页面 - 我将如何 1. 将 bobs 密码输入数据库以开始(散列) 2. 如何找回并确认哈希密码?

谢谢

【问题讨论】:

    标签: php mysql password-storage


    【解决方案1】:

    编辑 2017/11/09:一定要看看 O Jones 的答案。

    首先,MD5 并不是您可以尝试使用 sha256 或 sha512 的最佳哈希方法

    也就是说,让我们使用hash('sha256') 而不是md5() 来表示进程的散列部分。

    当您第一次创建用户名和密码时,您将使用一些盐(一些随机的额外字符添加到每个密码以使其更长/更强)对原始密码进行哈希处理。

    在创建用户表单中可能看起来像这样:

    $escapedName = mysql_real_escape_string($_POST['name']); # use whatever escaping function your db requires this is very important.
    $escapedPW = mysql_real_escape_string($_POST['password']);
    
    # generate a random salt to use for this account
    $salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
    
    $saltedPW =  $escapedPW . $salt;
    
    $hashedPW = hash('sha256', $saltedPW);
    
    $query = "insert into user (name, password, salt) values ('$escapedName', '$hashedPW', '$salt'); ";
    

    然后在登录时它看起来像这样:

    $escapedName = mysql_real_escape_string($_POST['name']);
    $escapedPW = mysql_real_escape_string($_POST['password']);
    
    $saltQuery = "select salt from user where name = '$escapedName';";
    $result = mysql_query($saltQuery);
    # you'll want some error handling in production code :)
    # see http://php.net/manual/en/function.mysql-query.php Example #2 for the general error handling template
    $row = mysql_fetch_assoc($result);
    $salt = $row['salt'];
    
    $saltedPW =  $escapedPW . $salt;
    
    $hashedPW = hash('sha256', $saltedPW);
    
    $query = "select * from user where name = '$escapedName' and password = '$hashedPW'; ";
    
    # if nonzero query return then successful login
    

    【讨论】:

    • 注意 - 你不应该对你打算散列的每个密码使用相同的盐。最好为每个密码使用唯一(随机)盐
    • 为什么要在 它被散列之前转义密码?我认为您应该转义要注入数据库的散列密码。
    • 您假设哈希返回二进制输出。可以,但您必须将其作为第三个参数传递,请参见 php.net/manual/en/function.hash.php 。由于第三个参数默认为 false 哈希仅返回安全的十六进制值。作为最佳实践,我逃避大多数来自表单的东西。我们也许可以在这里避免它,但总是这样做,然后检查没有它我们可能去哪里对我来说感觉更安全。
    • 我知道这个线程很老了,但是我很好奇如何编写盐解析查询......
    • 参见手册了解如何执行查询字符串然后解析结果:php.net/manual/en/function.mysql-query.php。其他数据库也类似。最易读的是 fetch_assoc 变体,如该链接中的 Example #2。然后你可以用类似的东西来获取盐字符串值: $row = mysql_fetch_assoc($result); $salt = $row['salt'];
    【解决方案2】:

    您必须根据密码进行推理:

    当 bob 注册到您的应用时,将密码存储为 md5('bob123');

    $query = "INSERT INTO users (username,password) VALUES('bob','".md5('bob123')."');
    

    那么,当 bob 登录时:

    $query = "SELECT * FROM users WHERE username = 'bob' AND password = '".md5('bob123')."';
    

    显然使用变量作为用户名和密码,这些查询是由 php 生成的,然后你可以在 mysql 上执行它们

    【讨论】:

    • 你应该在这个函数中加一个盐,使它更难破解表中的所有密码:$salt="1qTR3"; ... md5('bob123'.$salt)...。否则 - 喜欢你的解决方案!
    【解决方案3】:

    请不要使用 MD5 进行密码散列。这样的密码可以在几毫秒内被破解。您肯定会被网络犯罪分子控制。

    PHP 提供基于可靠随机盐和多轮 Rijndael / AES 加密的high-quality and future proof password hashing subsystem

    当用户首次提供密码时,您可以像这样散列它:

     $pass = 'whatever the user typed in';
     $hashed_password = password_hash( "secret pass phrase", PASSWORD_DEFAULT );
    

    然后,将 $hashed_password 存储在 MySQL 的 varchar(255) 列中。稍后,当用户想要登录时,您可以从 MySQL 中检索散列密码并将其与用户提供的登录密码进行比较。

     $pass = 'whatever the user typed in';
     $hashed_password = 'what you retrieved from MySQL for this user';
     if ( password_verify ( $pass , $hashed_password )) {
        /* future proof the password */
        if ( password_needs_rehash($hashed_password , PASSWORD_DEFAULT)) {
           /* recreate the hash */
           $rehashed_password = password_hash($pass, PASSWORD_DEFAULT );
           /* store the rehashed password in MySQL */
         }
         /* password verified, let the user in */
     }
     else {
         /* password not verified, tell the intruder to get lost */
     }
    

    这种面向未来的工作如何运作?未来的 PHP 版本将适应匹配更快、更容易破解的加密。如果需要重新散列密码以使其更难破解,password_needs_rehash() 函数的未来实现将检测到这一点。

    不要重新发明瘪胎。使用经过专业设计和审查的开源代码确保安全。

    【讨论】:

      【解决方案4】:

      插入:

      INSERT INTO ... VALUES ('bob', MD5('bobspassword'));
      

      检索:

      SELECT ... FROM ... WHERE ... AND password=md5('hopefullybobspassword');
      

      是您如何直接在查询中执行此操作的。但是,如果您的 MySQL 启用了查询日志记录,那么密码的明文将被写入此日志。所以...您希望在脚本中进行 MD5 转换,然后将生成的哈希值插入到查询中。

      【讨论】:

        【解决方案5】:

        PHP 有一个名为 md5 的方法 ;-) 只需 $password = md5($passToEncrypt);

        如果您在 SQL 中搜索,您也可以使用 MySQL 方法 MD5()....

         SELECT * FROM user WHERE Password='. md5($password) .'
        

        或 SELECT * FROM ser WHERE Password=MD5('.$password .')

        要插入它,你可以这样做。

        【讨论】:

          【解决方案6】:

          为什么不使用 MySQL 内置的密码哈希器:

          http://dev.mysql.com/doc/refman/5.1/en/password-hashing.html

          mysql> SELECT PASSWORD('mypass');
          +-------------------------------------------+
          | PASSWORD('mypass')                        |
          +-------------------------------------------+
          | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
          +-------------------------------------------+
          

          为了比较,你可以这样:

          select id from PassworTable where Userid='<userid>' and Password=PASSWORD('<password>')
          

          如果它返回一个值,那么用户是正确的。

          【讨论】:

            【解决方案7】:

            我并不擅长 PHP,但我认为这就是你所做的:

            $password = md5($password)

            $password 将是$_POST['password'] 或其他

            【讨论】:

              【解决方案8】:

              只需通过以下行获取哈希并将其存储到数据库中:

              $encryptedValue = md5("YOUR STRING");
              

              【讨论】:

              • 这既不是加密值,也不应该使用 MD5 对密码进行哈希处理。 password_hash() 函数是要走的路。
              【解决方案9】:

              为了进一步提高安全性,您可以使用 md5 加密以及两个不同的盐字符串,一个在 php 文件中定义的静态盐,然后为每个密码记录再随机生成一个唯一盐。

              以下是生成盐、md5 字符串和存储的方法:

                  $unique_salt_string = hash('md5', microtime()); 
                  $password = hash('md5', $_POST['password'].'static_salt'.$unique_salt_string);
                  $query = "INSERT INTO users (username,password,salt) VALUES('bob','".$password."', '".$unique_salt_string."');
              

              现在您有了一个静态盐,它对您的所有密码都有效,它存储在 .php 文件中。然后,在注册执行时,您会为该特定密码生成一个唯一的哈希。

              这一切都结束了:两个拼写完全相同的密码,将有两个不同的哈希值。唯一的哈希值与当前 ID 一起存储在数据库中。如果有人抓取数据库,他们将拥有每个特定密码的每个唯一盐。但他们没有的是你的静态盐,这让每个“黑客”的事情变得更加困难。

              这是您在 login.php 上检查密码有效性的方法,例如:

                   $user = //username input;
                   $db_query = mysql_query("SELECT salt FROM users WHERE username='$user'");
                   while($salt = mysql_fetch_array($db_query)) {
                          $password = hash('md5',$_POST['userpassword'].'static_salt'.$salt[salt]);
              }
              

              此方法非常强大且安全。如果要使用 sha512 加密,只需将其放在哈希函数中,而不是上面代码中的 md5。

              【讨论】:

              • MD5 不应该用于安全目的。如今,唯一可接受的哈希密码方法是通过password_hash()。此外,mysql_* 函数已被弃用,您的代码容易受到 SQL 注入的影响,这使得密码无关紧要。
              • 这是一个很好的例子,说明应该如何去做。 MD5 太快了,允许暴力破解10Giga MD5/sec。使用操作系统的随机源更好地创建盐,因为当前时间是可预测的并且有助于计划攻击。
              猜你喜欢
              • 1970-01-01
              • 2013-05-19
              • 1970-01-01
              • 2011-08-09
              • 1970-01-01
              • 1970-01-01
              • 2015-01-26
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多