如何安全地存储用户的密码?

2022-08-30 06:35:17

这比普通的MD5安全多少?我刚刚开始研究密码安全性。我对PHP很陌生。

$salt = 'csdnfgksdgojnmfnb';

$password = md5($salt.$_POST['password']);
$result = mysql_query("SELECT id FROM users
                       WHERE username = '".mysql_real_escape_string($_POST['username'])."'
                       AND password = '$password'");

if (mysql_num_rows($result) < 1) {
    /* Access denied */
    echo "The username or password you entered is incorrect.";
} 
else {
    $_SESSION['id'] = mysql_result($result, 0, 'id');
    #header("Location: ./");
    echo "Hello $_SESSION[id]!";
}

答案 1

确保密码存储方案安全的最简单方法是使用标准库

由于安全性往往比大多数程序员单独解决的要复杂得多,并且具有更多看不见的搞砸可能性,因此使用标准库几乎总是最简单,最安全(如果不是唯一的)可用选项。


新的 PHP 密码 API (5.5.0+)

如果您使用的是 PHP 版本 5.5.0 或更高版本,则可以使用新的简化密码哈希 API

使用 PHP 密码 API 的代码示例:

<?php
// $hash is what you would store in your database
$hash = password_hash($_POST['password'], PASSWORD_DEFAULT, ['cost' => 12]);

// $hash would be the $hash (above) stored in your database for this user
$checked = password_verify($_POST['password'], $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}

(如果您仍在使用旧版 5.3.7 或更高版本,则可以安装 ircmaxell/password_compat 以访问内置功能)


改善咸土豆泥:加入胡椒粉

如果你想要额外的安全性,现在(2017年)的安全人员建议在(自动)盐渍密码哈希中添加一个“胡椒”。

有一个简单的,直接的类可以安全地实现这种模式,我建议:Netsilik/PepperedPasswordsgithub)。
它带有MIT许可证,因此您可以根据需要使用它,即使在专有项目中也是如此。

代码使用示例:Netsilik/PepperedPasswords

<?php
use Netsilik/Lib/PepperedPasswords;

// Some long, random, binary string, encoded as hexadecimal; stored in your configuration (NOT in your Database, as that would defeat the entire purpose of the pepper).
$config['pepper'] = hex2bin('012345679ABCDEF012345679ABCDEF012345679ABCDEF012345679ABCDEF');

$hasher = new PepperedPasswords($config['pepper']);

// $hash is what you would store in your database
$hash = $hasher->hash($_POST['password']);

// $hash would be the $hash (above) stored in your database for this user
$checked = $hasher->verify($_POST['password'], $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}


旧的标准库

请注意:您不再需要它了!这只是为了历史目的。

看看:便携式PHP密码哈希框架phpass,并确保尽可能使用该算法。CRYPT_BLOWFISH

使用 phpass (v0.2) 的代码示例:

<?php
require('PasswordHash.php');

$pwdHasher = new PasswordHash(8, FALSE);

// $hash is what you would store in your database
$hash = $pwdHasher->HashPassword( $password );

// $hash would be the $hash (above) stored in your database for this user
$checked = $pwdHasher->CheckPassword($password, $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}

PHPass已经在一些非常知名的项目中实施:

  • phpBB3
  • WordPress 2.5+ 以及 bbPress
  • Drupal 7 版本(模块可用于 Drupal 5 和 6)
  • 别人

好消息是,您不必担心细节,这些细节已经由有经验的人编程,并由互联网上的许多人审查。

有关密码存储方案的详细信息,请阅读 Jeff 的博客文章:您可能错误地存储了密码

无论你做什么,如果你选择“我会自己做,谢谢”的方法,不要再使用MD5SHA1它们是很好的哈希算法,但出于安全目的被认为是损坏的

目前,使用加密和CRYPT_BLOWFISH是最佳做法。
PHP中的CRYPT_BLOWFISH是Bcrypt哈希的实现。Bcrypt基于Blowfish块密码,利用其昂贵的密钥设置来减慢算法的速度。


答案 2

如果您使用参数化查询而不是串联 SQL 语句,则用户将更加安全。对于每个用户都应该是唯一的,并且应该与密码哈希一起存储。


推荐