3

在网上研究和寻求帮助后,我现在正在创建一个 sha2 登录表单,我发现下面这个链接中的示例代码非常有用和实用(我希望我是对的!??),唯一我不明白的是这个程序员编写函数并从函数中获取盐值的方式。

http://hungred.com/useful-information/php-better-hashing-password/

define('SALT_LENGTH', 15);

function HashMe($phrase, &$salt = null)
{
    $pepper = '!@#$%^&*()_+=-{}][;";/?<>.,';

    if ($salt == '')
    {
        $salt = substr(hash('sha512',uniqid(rand(), true).$pepper.microtime()), 0, SALT_LENGTH);
    }
    else
    {
        $salt = substr($salt, 0, SALT_LENGTH);
    }

    return hash('sha512',$salt . $pepper .  $phrase);
}

如果我将功能更改为此有什么区别?

function HashMe($phrase, $salt)  {..}

当然这个函数会失败,在 $salt 之前有一个 '&' 有什么用?有必要像这样&$salt = null 'null'吗?如果我输入 '&$salt' 会怎样?

然后,为了得到盐值,你可以直接把它放在下面的 sql 查询中,

$username = cleanMe($_POST('username'));
$password = cleanMe($_POST('password'));
$salt = '';
$hashed_password = HashMe($password, $salt);
$sqlquery = 'INSERT INTO  `usertable` ("username", "password", "salt") VALUES  ("'.$username.'", "'.$hashed_password .'", "'.$salt.'") WHERE 1';
..

在准备 sql 查询之前,如何从下面的函数中获取盐值,

$salt = "'".salt."'";
$username = "'".$username."'";
$hashed_password = "'".$hashed_password."'";

然后,

$sqlquery = 'INSERT INTO  `usertable` ("username", "password", "salt") VALUES  ($username, $hashed_password, $salt) WHERE 1';

我不喜欢/不想在我的 sql 查询中使用这个 - "'" 的原因是我有时有空值,例如 $firstname = 'NULL'; 如果名字为空/空,我希望该行将空字段“勾选”为空。

此外,在我的 sql 查询中有“'”,当出现问题时让我头晕目眩并且难以调试......

对不起,我在这个线程中有很多问题!

谢谢。

4

1 回答 1

5

看看我能不能一次一个地回答你的问题。

首先,您问为什么function HashMe($phrase, $salt)失败,而function HashMe($phrase,&$salt = null)没有。这将在解释第二部分和第三部分后变得清晰。

其次,您问为什么$salt在函数声明中需要 & before。& 的意思是你通过引用传递值。通常,当您将值传递给函数时,会创建该值的副本并处理该副本。例如:

function addOne($number){
    $number = $number + 1;
}

$myNumber = 3;
addOne($myNumber);
echo $myNumber;

此代码将输出3,而不是4。这是因为该函数不会更改 $myNumber,它会创建它的副本并更改该副本。当您通过引用传递时,您告诉它使用原始编号而不是创建副本。因此,如果我们做这个微小的改变:

function addOne(&$number){
    $number = $number + 1;
}

$myNumber = 3;
addOne($myNumber);
echo $myNumber;

现在我们的代码输出4. 该函数通过引用传递 $salt,因为它改变了 $salt 的值。因此,在函数运行后,您现在有了 $salt 的新值。

至于为什么需要&$salt = null,如果您自己不声明变量,那就是自动声明变量。因此,如果您只想生成一个随机哈希(由于您不知道使用了什么盐,因此无法重新创建它),您可以使用HashMe("message to hash");. = null意思是如果没有第二个参数,自动设置第二个参数为“null” 。然而,在后面的代码中,它说如果第二个参数为“null”,则生成一个随机盐:

if ($salt == '')
{
    $salt = substr(hash('sha512',uniqid(rand(), true).$pepper.microtime()), 0, SALT_LENGTH);
}

因此,如果您以这种方式调用该函数,您将创建一个您可能永远无法重现的散列。

对于您的第四个问题,您想获取 $salt 的值以在 SQL 查询中使用。这就是通过引用传递的美妙之处。由于变量 $salt 是通过引用传递的,因此在函数运行后,您可以再次使用 $salt 并且它将具有新值。需要注意的一件重要事情是更改$salt 的所有功能都是确保它的长度为 15 个字符。任何较长的内容都会被截断,但较短的内容将保持不变。出于这个原因,如果您存储函数返回的(15 个字符)盐,您可以在将来使用它并且它不会再次更改盐。所以你的 SQL 查询应该可以完美运行。

$sqlquery = "INSERT INTO  `usertable` ('username', 'password', 'salt') VALUES  ($username, $hashed_password, $salt) WHERE 1";

请注意,我交换了原始查询中的双引号和单引号。这是因为在某些版本的 PHP 中,变量不会被解析为单引号。例如:

$secret = "Hello, there";
echo '$secret'; // "$secret"
echo "$secret"; // "Hello, there"
于 2010-10-10T02:43:50.363 回答