我想使用salt和hash来创建安全登录。我尝试按照this tutorial编写自己的代码,但它总是返回false。这是我的代码:
require_once 'application/third_party/Secure-Login/classes/Hashing.php';
require_once 'application/third_party/Secure-Login/classes/Salt.php';
$password = Hashing::create_hash('123456', Salt::random(12));
$old = '$2a$10$zuzycDw3Ack2cCoL3ds1sudJ2WioZ87.75ErLZVcZyh4d1hS2rHFu';
if (Hashing::validate($password, $old, Salt::random(12))) {
echo true;
} else {
echo false;
}
我包括两个课程:
<?php
class Hashing {
function __construct() {}
/**
* @param string $pass The user submitted password
* @param string $hashed_pass The hashed password pulled from the database
* @param string $salt The salt pulled from the database
* @param string $hash_method The hashing method used to generate the hashed password
*/
static function validate($pass, $hashed_pass, $salt, $hash_method = 'sha1') {
if (function_exists('hash') && in_array($hash_method, hash_algos())) {
return ($hashed_pass === hash($hash_method, $salt . $pass));
}
return ($hashed_pass === sha1($salt . $pass));
}
/**
* Generates a secure, pseudo-random password with a safe fallback.
*/
static function pseudo_rand($length) {
if (function_exists('openssl_random_pseudo_bytes')) {
$is_strong = false;
$rand = openssl_random_pseudo_bytes($length, $is_strong);
if ($is_strong === true) {
return $rand;
}
}
$rand = '';
$sha = '';
for ($i = 0; $i < $length; $i++) {
$sha = hash('sha256', $sha . mt_rand());
$chr = mt_rand(0, 62);
$rand .= chr(hexdec($sha[$chr] . $sha[$chr + 1]));
}
return $rand;
}
/**
* Creates a very secure hash. Uses blowfish by default with a fallback on SHA512.
*/
static function create_hash($string, $salt = '', $hash_method = 'sha1', $stretch_cost = 10) {
$salt = Hashing::pseudo_rand(128);
$salt = substr(str_replace('+', '.', base64_encode($salt)), 0, 22);
if (function_exists('hash') && in_array($hash_method, hash_algos())) {
return crypt($string, '$2a$' . $stretch_cost . '$' . $salt);
}
return Hashing::_create_hash($string, $salt);
}
/**
* Fall-back SHA512 hashing algorithm with stretching.
*/
static function _create_hash($password, $salt) {
$hash = '';
for ($i = 0; $i < 20000; $i++) {
$hash = hash('sha512', $hash . $salt . $password);
}
return $hash;
}
}
<?php
class Salt {
public static function random($len = 8) {
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*()-=_+';
$l = strlen($chars) - 1;
$str = '';
for ($i = 0; $i < $len; ++$i) {
$str .= $chars[rand(0, $l)];
}
return $str;
}
}
请检查帮帮我!我不知道哪里出错了,它是如何运作的。非常感谢!
答案 0 :(得分:1)
您的代码存在许多问题,因此我强烈建议使用函数password_hash()和password_verify()进行散列。
因为你说你想了解它的工作原理,这里有一些提示:
static function create_hash($string, $salt = '', $hash_method = 'sha1', $stretch_cost = 10) {
$salt = Hashing::pseudo_rand(128);
$salt = substr(str_replace('+', '.', base64_encode($salt)), 0, 22);
if (function_exists('hash') && in_array($hash_method, hash_algos())) {
return crypt($string, '$2a$' . $stretch_cost . '$' . $salt);
}
return Hashing::_create_hash($string, $salt);
}
此方法首先尝试使用crypt()
这是好的,因为它会生成BCrypt哈希。如果成本参数小于10,则成本参数将失败,并且可能会生成不安全的盐,并且它使用池中过多的熵。然后它检查hash()
函数是否存在,但是这个函数根本不是哈希密码,而是与crypt()无关。
稍后要验证您不使用crypt()
,而是使用hash()
功能检查,这是与以前不同的算法。然后无法自由选择盐来验证密码,而是需要与生成哈希相同的盐,crypt()函数实际上确实在哈希值中包含了这个盐。
static function validate($pass, $hashed_pass, $salt, $hash_method = 'sha1') {
if (function_exists('hash') && in_array($hash_method, hash_algos())) {
return ($hashed_pass === hash($hash_method, $salt . $pass));
}
return ($hashed_pass === sha1($salt . $pass));
}
如果您想了解更多关于密码哈希的知识,我会邀请您阅读关于secure password storing的教程。
答案 1 :(得分:1)
如果你真的想让自己的生活更轻松。你可以去PHPASS
库,它提供了你可以使用的功能。您只需要创建该类的对象并使用这些函数。
查看以下链接: 您可以从这里下载库: Download PHPASS
您可以从此处获取更多信息: Sample usage of the library
答案 2 :(得分:0)
您的示例中的一个问题是,每次要验证密码时都使用新盐,而不是使用旧盐。实际上,您需要存储用于散列密码的盐,以便对其进行验证。
请尝试以下代码:
$salt = Salt::random(12);
$password = Hashing::create_hash('123456', $salt);
验证:
if (Hashing::validate('123456', $password, $salt)) {
echo true;
} else {
echo false;
}
当然,每次要散列新密码时,您都需要生成一个新的盐。