【问题标题】:Passwords do not match when hashing/salting哈希/加盐时密码不匹配
【发布时间】:2012-07-05 14:23:14
【问题描述】:

好的,所以下面的所有代码都不是我自己的。我一直在关注互联网上的教程,但是当我尝试运行它时,似乎没有密码匹配。我相信加盐密码可能会出错,因为数据库中的内容与 login.php 脚本中描述的 64 个字符相去甚远。我不知道。代码如下:

register.php

// Create a 256 bit (64 characters) long random salt
// Let's add 'something random' and the username
// to the salt as well for added security
$salt = hash('sha256', uniqid(mt_rand(), true) . 'something random' . strtolower($username));

// Prefix the password with the salt
$hash = $salt . $password;

// Hash the salted password a bunch of times
for ( $i = 0; $i < 100000; $i ++ )
{
    $hash = hash('sha256', $hash);
}

// Prefix the hash with the salt so we can find it back later
$hash = $salt . $hash;

// carry on with registration code...

登录.php

$email = $_POST['email'];
$password = $_POST['password'];

$con = mysql_connect("localhost", "redacted", "redacted", "redacted");

$sql = '
    SELECT
        `password`
    FROM `users`
        WHERE `email` = "' . mysql_real_escape_string($email) . '"
    LIMIT 1
    ;';

$r = mysql_fetch_assoc(mysql_query($sql));

// The first 64 characters of the hash is the salt
$salt = substr($r['password'], 0, 64);

$hash = $salt . $password;

// Hash the password as we did before
for ( $i = 0; $i < 100000; $i ++ )
{
    $hash = hash('sha256', $hash);
}

$hash = $salt . $hash;

if ( $hash == $r['password'] )
{
    session_start();
    header('Location: /quiz/index.php');
}

if( $hash != $r['password'] ){
    session_start();
    header('Location: /?error=4');
}

// end login script

【问题讨论】:

  • 哪个教程? PHP 在网络上有大量糟糕的教程。这似乎是其中之一。
  • 一个常见的错误是数据库字段不够长,无法存储所有字符。
  • 啊……这就是原因。我的密码字段只有 30 个字符。干杯@Konerak :-)
  • @Konerak 完成!再次欢呼。 :-)

标签: php mysql hash passwords salt


【解决方案1】:

一个常见错误是数据库字段的长度不足以存储所有字符。密码将永远不会等于用户输入的密码。

对于这种功能,请始终编写单元测试来检查功能(仍然)是否按预期工作。总有一天会有人修改数据库,修改hash算法,修改salt……没人能登录。

【讨论】:

    【解决方案2】:

    看起来你加了 2 次盐:

    $hash = $salt . $password;
    
    // Hash the password as we did before
    for ( $i = 0; $i < 100000; $i ++ )
    {
        $hash = hash('sha256', $hash);
    }
    
    //skip the below one
    $hash = $salt . $hash;
    

    更新:

    确实,在这种情况下需要添加 2 次盐。

    虽然盐应该保存在单独的 db 列中,因此代码将更加简化 - 通过避免用于存储/检索盐的所有字符串连接。

    除此之外,通过将每条信息存储在单独的槽中,您的数据库结构将更接近第三范式

    【讨论】:

    • 也跳过整个“hash it many times”。只需使用可以引入工作因素的东西,通常推荐使用 bcrypt。
    • 您需要将盐与哈希一起存储,以便您知道它之后是什么。
    • 原来我的密码数据库字段太短了。但感谢所有建议。
    • 如果您将盐保存在不同的数据库列中,您的代码会大大简化,并且您的数据库会得到应有的使用
    • 对不起,这是错误的。您需要添加两次盐:第一次,所以它与密码(盐的实际点)进行哈希处理。第二次,能够取回盐。更好的选择是将盐存储在单独的数据库列中,并且重命名此脚本中的变量也不会受到伤害。在散列之前和之后,一切都是$hash$tohash$hashed$salt_with_hashed 可能是更清晰的变量名称。
    猜你喜欢
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 2013-09-11
    • 2010-11-30
    • 1970-01-01
    相关资源
    最近更新 更多