如何在加盐哈希密码后进行登录?

3

这是我对此的第二次编辑。我已经苦思冥想了几天,感觉我已经很接近了。我尝试了许多不同版本的第三个代码块,但就是无法得到正确结果。你有什么想法,我做错了什么(更改的是第三个代码块)。

if(!$error) {
    $alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcedfghijklmnopqrstuvwxyz1234567890";
    $rand = str_shuffle($alpha);
    $salt = substr($rand,0,40);
    $hashed_password = sha1($salt . $_POST['Password']);
    $query = "INSERT INTO `Users` (
                `FirstName`,
                `LastName`,
                `Email`,
                `Password`,
                `salt`,
                `RelationshipToCF`,
                `State`,
                `Gender`,
                `Birthday`,
                `Status`
        )VALUES(
                '" . mysql_real_escape_string($_POST['firstName']) . "',
                '" . mysql_real_escape_string($_POST['lastName']) . "',
                '" . mysql_real_escape_string($_POST['email']) . "',
                '" . $hashed_password . "',
                '" . $salt . "',
                '" . mysql_real_escape_string($_POST['RelationToCF']) . "',
                '" . mysql_real_escape_string($_POST['State']) . "',
                '" . mysql_real_escape_string($_POST['sex']) . "',
                '" . mysql_real_escape_string($_POST['DateOfBirth_Year'] . "-" . $_POST['DateOfBirth_Month'] . "-" . $_POST['DateOfBirth_Day']) . "',
                'pending'
    )";
    mysql_query($query, $connection);

这是我正在使用的更新现有密码的方法:

$query = "SELECT * FROM `Users`";
$request = mysql_query($query,$connection);
while($result = mysql_fetch_array($request)) {
    $alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcedfghijklmnopqrstuvwxyz1234567890";
    $rand = str_shuffle($alpha);
    $salt = substr($rand,0,40);
    $hashed_password = sha1($salt . $result['Password']);
    $user = $result['id'];

    $query2 = "UPDATE `Users` SET `salt` = '$salt' WHERE `id` = '$user'";
    $request2 = mysql_query($query2,$connection) or die(mysql_error());
    $query3 = "UPDATE `Users` SET `encrypted_passwords` = '$hashed_password' WHERE `id` = '$user'";
    $request3 = mysql_query($query3,$connection) or die(mysql_error());
}

现在,我希望允许用户使用他们注册时的密码进行登录,但目前只能使用哈希密码进行登录。显然,这还没有应用到真正的数据库中。

以下是我需要修改的登录页面查询:

    if(isset($_POST['subSignIn']) &&
       !empty($_POST['email']) &&
       !empty($_POST['password'])) {

        $email = mysql_real_escape_string($_POST['email']);
        $password = mysql_real_escape_string($_POST['password']);
        $query = "SELECT
             `id`,`email`,`password` FROM `Users`
             WHERE `Email` = '" . $email . "' AND
             `Password` = '" . $password . "'  &&
             `Status` = 'active' LIMIT 1";
        $request = mysql_query($query,$connection) or die(mysql_error());

        if(@mysql_num_rows($request)) {

            $result = mysql_fetch_array($request);
            $_SESSION['LIFE']['AUTH'] = true;       
            $_SESSION['LIFE']['ID'] = $result['id'];

$query = "UPDATE `Users` SET` LastActivity` = '" . date("Y-m-d") ." " . date("g:i:s") . "'   WHERE `id` ='" .mysql_real_escape_string($_SESSION['LIFE']['ID']) . "' LIMIT 1";

            mysql_query($query,$connection);

            if(!empty($_POST['return'])) {          
                header("Location: " . $_POST['return']);        
            }else{
                header("Location: Dashboard.php?id=" . $_SESSION['LIFE']['ID']);
            }
        }else{
            $_SESSION['LIFE']['AUTH'] = false;      
            $_SESSION['LIFE']['ID'] = false;    
        }

我一直在搜索网络上的方法,但是想要利用这里所有伟大的思维来寻求建议/方法/教程/指引。

<== 在原先的5个答案之后,这是我的尝试 ==>

 i

f(isset($_POST['subSignIn']) && !empty($_POST['email']) && !empty($_POST['password'])) {


    $query = "SELECT id FROM cysticUsers WHERE Email = '$email' AND Password = SHA1(CONCAT(salt,'$password')) AND Status = 'active' LIMIT 1";
    $request = mysql_query($query,$connection) or die(mysql_error());

if(@mysql_num_rows($request)) {

        $row = mysql_fetch_assoc($request);
        if (sha1($row['salt'] . $_POST['password']) === $row['password']) {


        $_SESSION['CLIFE']['AUTH'] = true;
        $_SESSION['CLIFE']['ID'] = $result['id'];

        // UPDATE LAST ACTIVITY FOR USER
        $query = "UPDATE `cysticUsers` SET `LastActivity` = '" . date("Y-m-d") . " " . date("g:i:s") . "' WHERE `id` = '" . mysql_real_escape_string($_SESSION['CLIFE']['ID']) . "' LIMIT 1";
        mysql_query($query,$connection);

        if(!empty($_POST['return'])) {
            header("Location: " . $_POST['return']);

        }else{
            header("Location: CysticLife-Dashboard.php?id=" . $_SESSION['CLIFE']['ID']);
            }
        }

    }else{

        $_SESSION['CLIFE']['AUTH'] = false;
        $_SESSION['CLIFE']['ID'] = false;

    }
}

?>

1
您是指如何验证输入的密码,对吗? - Gumbo
你应该适当缩进你的代码,使其易读且一致。 - ircmaxell
5个回答

3
如果您想验证输入的密码,可以像验证原始密码一样进行:在值之前添加盐并对该值进行哈希。
因此,查找哈希原始密码时使用的盐,并在对输入密码进行哈希时使用它,然后将存储的哈希与新计算的哈希进行比较。基本上是这样的:
$query = "SELECT `salt`, `password` FROM `Users` WHERE `Email` = '" . $email . "'";
$request = mysql_query($query,$connection) or die(mysql_error());
if (mysql_num_rows($request)) {
    $row = mysql_fetch_assoc($request);
    if (sha1($row['salt'] . $_POST['Password']) === $row['password']) {
        // user authentic
    } else {
        // user not authentic
    }
}

如果它们相同,输入的密码很可能与原始输入的密码相同。

唯一的可能性是因为总会有两个输入值具有相同的哈希值,这种情况被称为碰撞攻击

我认为你应该稍微详细解释一下“可能”的含义 :) - mpen
@JoshK 即使为每个用户使用唯一的哈希和盐,这种情况仍有可能发生吗? - LightningWrist
1
@Lightening:概率非常低。MD5碰撞已经通过字节数组而不是实际条件进行了演示。 - Josh K

3

我没有时间逐个查看整个代码块,但基本的盐/哈希验证如下:

$user         // User has a $password and a $salt. $password = hash($plaintext . $salt);
$password     // Password we are checking.
return $user->password == hash($password . $user->salt);

@Mark:是的,我知道。最近一直在处理非 PHP 东西。我也差点忘记了 $ 符号。 - Josh K

1

你能让第三个代码块更易读吗?


这是我会做的方式 -

  • 在注册时加密,存储密码+盐。
  • 当他们登录时,获取与他们尝试登录的用户名相关联的盐。
  • 使用数据库中的盐对他们输入的密码(登录时)进行哈希处理。
  • 将登录密码与数据库中的密码进行比较。

应该很容易。

例如:

$hashed_password = sha1($salt . $result['Password']);

在您的数据库中存储 $hashed_password$salt

当他们登录时,您将比较上面的 $hashed_password 与类似以下内容的密码:

$password = sha1($row['salt'] . $_POST['password']);

有意义吗?


1

首先,您需要通过搜索输入的用户名从数据库中获取盐密钥,然后使用从数据库中获取的盐对输入的密码进行哈希处理,并检查它是否与数据库中该用户名的密码匹配。代码大致如下:

$query = "SELECT salt FROM Users WHERE username='$user'";
$result = mysql_query($query) or die ("AAAAGH!  *Thud*");
$row = mysql_fetch_assoc($result);
$salty_password = sha1($row['salt'], $_POST['password']);
$query = "SELECT * FROM users WHERE username='$user' AND password='$salty_password'";
$result = mysql_query($query) or die ("AAAAGH!  *Thud*");
if (mysql_num_rows($result)) {
    echo "Successfully authenticated!";
}
else {
    echo "Failed to Authenticate.";
}

1

看起来好像当用户创建账号时,您实际上没有使用他们的密码。

在第一个代码块中:

$hashed_password = sha1($salt . $result['Password']);

应该是这样的:

$hashed_password = sha1($salt . $_POST['Password']);

我认为你只存储了哈希盐,基本上允许使用空密码登录!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接