0

基本上我有一个游戏服务器,其中密码哈希为 sha1,另一个为 md5,用于新用户注册帐户时。我决定坚持使用 sha1,但是我希望我的用户能够更改他们的密码,这会将他们从 md5 创建为 sha1。

我已经编写了以下代码,但它似乎不起作用。

基本上,我希望他们在更改密码时将 md5 替换为 sha1 哈希密码。

    <?php
if(isSet($_POST['submit']))
{
$changePW = true;
}
?>

<?php
public function hashed($password)

 {

  return sha1($password . "xCg532%@%gdvf^5DGaa6&*rFTfg^FD4\$OIFThrR_gh(ugf*/");

 }
?>

<?php
if(isset($changePW))
{
    //host, username, password, dbName
    $con=mysqli_connect("localhost","root","password","dbName");

    $username = $_POST['username'];
    $password = $_POST['passwordOld'];
    $passwordNew1 = $_POST['passwordNew1'];
    $passwordNew2 = $_POST['passwordNew2'];

    $passwordHash = md5($password);

// Check connection
if (mysqli_connect_errno())
  {
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
  }

  $cmd = "SELECT COUNT(*) FROM users WHERE username = '" . $username . "' AND password = '" . $passwordHash . "'";
  $result = mysqli_query($con,$cmd);
  $row = mysqli_fetch_row($result);
  if($row[0] == 1)
  {
      if($passwordNew1 == $passwordNew2)
      {
          $newHash = hashed($passwordNew1);
          $cmd = "UPDATE users SET password = '$newHash' WHERE username = '$username'";
          mysqli_query($con,$cmd);
      }
      else{
          $passwordMatch = true;
      }
  }
 else {
      $detailsError = true;
  }

  //$hash = md5($password);
  //mysqli_query($con,"INSERT INTO tutorials_tbl (name, hash) VALUES ('" . $username . "','" . $hash . "')");

mysqli_close($con);
}
?>

<head>
    <style type="text/css">
        .lblLabel{
            width:165px;
            display: inline-block;
        }
    </style>
</head>

<form name="login" method="post" action="change.php">

<fieldset style="width:350px;"><legend>Change Password Form</legend>

<label class="lblLabel">Username</label><input id="name" type="text" name="username" value=""><br />

<label class="lblLabel">Old Password</label><input type="password" name="passwordOld"><br />
<?php
    if(isset($detailsError))
    { ?>
<span style="color: #F00; font-weight: bold;">Username or Password Incorrect</span>
    <?php }
    ?>
<label class="lblLabel">New Password</label><input type="password" name="passwordNew1"><br />

<label class="lblLabel">Repeated New Password</label><input type="password" name="passwordNew2"><br />
<?php
    if(isset($passwordMatch))
    { ?>
<span style="color: #F00; font-weight: bold;">Password's do not match</span>
    <?php }
    ?>
<label class="lblLabel">&nbsp;</label><input id="submit" type="submit" name="submit" value="Change Password"><br />
</fieldset>

</form>

它正在调用将用户表中密码列下的密码更改为sha1。users表中所有当前密码都是md5,需要转换成sha1。

对不起,如果这没有意义。

4

2 回答 2

2

每个密码存储系统都必须具有切换到更好的哈希算法的选项,您的问题不是一次性迁移问题。像 BCrypt 这样好的密码哈希算法有一个成本因素,有时您必须增加这个成本因素(因为更快的硬件),然后您需要与迁移所需的完全相同的过程。

这导致了你最大的问题,SHA-1 不适合散列密码,特别是如果它是用恒定盐加盐的。它的速度太快了,很容易暴力破解(2013 年使用普通硬件每秒 3 Giga 哈希)。这就是为什么人们应该使用像 BCrypt 这样的慢速密钥派生函数。如果您努力迁移您的哈希,那么最好直接切换到 BCrypt。

切换到更好的哈希算法的通常方法是等到用户下次登录(与您的示例相反,用户不需要更改密码)。然后你采取以下步骤:

  1. 首先尝试使用新算法验证输入的密码。新密码和已转换的密码将不再需要更长的时间进行验证。
  2. 如果不匹配,则将其与旧的哈希算法进行比较。
  3. 如果旧的哈希值匹配,那么您可以计算并存储新的哈希,因为您知道密码。

该系统可以扩展到多个迁移。只要确保您首先检查最新算法,然后检查旧算法。那么只有在用户下次登录时,登录才会花费更长的时间,并且新用户不会受到向后兼容性问题的影响。

这就留下了如何使用 BCrypt 的问题。PHP 5.5 将有自己的函数password_hash()和 password_verify() 准备好。我建议使用这个优秀的 api,或者它是早期 PHP 版本的兼容包。用法非常简单:

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

➽ 请记住,您需要一个长度为 60 个字符的数据库字段来存储此类哈希值。

于 2013-06-21T09:15:20.963 回答
0

正如我在评论中解释的那样,为了使用户在密码存储中的过渡尽可能顺利,您要做的是将每个人的密码与 SHA1 进行哈希处理,同时将其保留为 MD5-hashed。然后,在您的正常登录逻辑中,您将对密码进行 MD5 哈希处理,然后对其进行 SHA1 哈希处理。

顺便说一句,我将 SHA2 用于哈希算法(同样快速、更安全等)

<?php
public function hashSpecial($password)
{
    return sha1($password . "xCg532%@%gdvf^5DGaa6&*rFTfg^FD4\$OIFThrR_gh(ugf*/");
}

public function hashForLogin($password)
{
    return sha1(md5($password) 
        . "xCg532%@%gdvf^5DGaa6&*rFTfg^FD4\$OIFThrR_gh(ugf*/");
}

public function hashAllPasswords()
{
    $con = mysqli_connect("localhost", "root", "password", "dbName");

    $query = 'SELECT username, password FROM users';
    if(mysqli_connect_errno() > 0)
    {
        echo 'Failed to connect to database.';
        break;
    }
    else
    {
        $result = mysqli_query($con, $query);
        while(($row = mysqli_fetch_row($result)) != null)
        {
            $query = 'UPDATE users SET password=\'' 
                 . hashSpecial($row['password']) . '\' WHERE username=\''
                 . $row['username'] . '\'';
            $r2 = mysqli_query($con, $query);
        }
    }
}
?>
于 2013-06-20T19:43:45.103 回答