正确的方法来存储和检索SHA-256散列和盐渍密码

时间:2014-03-03 16:37:45

标签: php security hash passwords salt

这是我第一次安全存储密码,我想确保一切都正确完成。我被建议在盐旁边使用SHA-256哈希。

假设用户提交了密码表格,我们会通过

获取密码
$password = $_POST["password"];

使用salt $ password并在其上使用SHA-256哈希的正确方法是什么,所以它可以存储在数据库中的密码字段“password CHAR(64)”中?

一旦完成并存储,我将如何将存储在数据库中的值与在登录表单中输入的一个用户进行比较?假设$loginPassword = $_POST["loginPassword"];是用户输入的内容。

2 个答案:

答案 0 :(得分:2)

您可以使用crypt()函数为您添加SHA系列方法,而不是使用SHA系列方法。

以下是使用PDO的示例脚本(保存和登录)。

在DB中保存密码

<?php
// Set the password
$password = 'mypassword';

// Get the hash, letting the salt be automatically generated
$hash = crypt($password);

echo $hash; // for testing purposes only

$mysql_username = 'username'; // for DB
$mysql_password = 'password'; // for DB

$dbh = new PDO('mysql:host=localhost;dbname=database_name', $mysql_username, $mysql_password);

$stmt = $dbh->prepare("INSERT INTO table_name (name,pass) VALUES (:name,:pass)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':pass', $pass);

// insert rows
// $name = $_POST['name'];
// $name = $_POST['pass'];

$name = "username";
$pass = $hash;
$stmt->execute();

登录脚本

<?php
$mysql_username = 'username'; // for DB
$mysql_password = 'password'; // for DB

$dbh = new PDO('mysql:host=localhost;dbname=database_name', $mysql_username, $mysql_password);

/*
$username = $_POST['username'];
$password = $_POST['password'];
*/

$username = "username";
$password = "mypassword";

$sql = "SELECT * FROM table_name WHERE name=:username";
$statement = $dbh->prepare($sql);
$statement->bindValue(':username',$username,PDO::PARAM_STR);

if($statement->execute())
{
    if($statement->rowCount() == 1)
    {
        $row = $statement->fetch(PDO::FETCH_ASSOC);

 if (crypt($password, $row['pass']) === $row['pass'])

        {
            $username = $row['name'];
            $email = $row['email'];

echo "Stage 1";

echo "<hr noshade size=\"1\">";

echo "Hello " .$username;

            exit;
        }
        else
        {
            // include "error_login.php";

echo "Stage 2 - ERROR";

        }
    }
    else
    {
       // include "error_login.php";

echo "Stage 3 error";
    }
}

答案 1 :(得分:2)

如果您使用的是PHP 5.5或更高版本,那么内置的密码_hash()和密码_verify()以及Bcrypt - 如果您使用的是PHP 5.3.7或更高版本,那么就是password_compat兼容性库;所有这些都是PHP.net Safe Password Hashing FAQ entry

基本上,在PHP 5.3.7及更高版本上,用password_hash()和password_verify()替换旧的crypt()。

有关成本选择的详细信息,请参阅my answer to PHP Secure password generation and storage,但它归结为非常简单:

<?php
/**
 * In this case, we want to increase the default cost for BCRYPT to 12.
 * Note that we also switched to BCRYPT, which will always be 60 characters.
 */
$options = [
    'cost' => 12,
];
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
?>

生成哈希,然后存储输出字符串,然后验证:

<?php
// See the password_hash() example to see where this came from.
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';

if (password_verify('rasmuslerdorf', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}
?>

这两个例子都来自PHP.net Password Hashing page