PHP安全性sha2:&$ salt = null?

lau*_*kok 3 php security function sha2

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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

function HashMe($phrase, $salt)  {..}
Run Code Online (Sandbox Code Playgroud)

当然这个功能会失败,在$ salt之前有一个'&'是什么?是否有必要像这样'null'&$ salt = null?如果我把'&$ salt'怎么办?

然后,为了获得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';
..
Run Code Online (Sandbox Code Playgroud)

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

$salt = "'".salt."'";
$username = "'".$username."'";
$hashed_password = "'".$hashed_password."'";
Run Code Online (Sandbox Code Playgroud)

然后,

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

我不喜欢/想要这个的原因 - 我的SQL查询中的"'"是我有时候像$ firstname ='NULL'那样有空值; 如果firstname为空/ null,我希望行将空字段"勾选"为null.

此外,在我的SQL查询中使用"'",让我头晕并且在出错时难以调试...

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

谢谢.

ste*_*esu 5

让我们看看我是否可以一次回答一个问题.

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

其次,你$salt在函数声明中询问为什么需要&之前的&.你通过引用传递价值的意义和方法是什么.通常,当您将值传递给函数时,会创建该值的副本,并且您可以处理该副本.例如:

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

$myNumber = 3;
addOne($myNumber);
echo $myNumber;
Run Code Online (Sandbox Code Playgroud)

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

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

$myNumber = 3;
addOne($myNumber);
echo $myNumber;
Run Code Online (Sandbox Code Playgroud)

现在我们的代码输出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);
}
Run Code Online (Sandbox Code Playgroud)

因此,如果以这种方式调用函数,您将创建一个您可能永远无法再现的哈希.

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

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

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

$secret = "Hello, there";
echo '$secret'; // "$secret"
echo "$secret"; // "Hello, there"
Run Code Online (Sandbox Code Playgroud)