如何在登录中使用salt和hash?
How to use salt and hash in login?
我想使用 salt 和 hash 来创建安全登录。我尝试遵循 this tutorial 并编写自己的代码,但它总是 return 错误。这是我的代码:
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 = 'a$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, 'a$' . $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;
}
}
请查收帮帮我!我不知道哪里出了问题以及它是如何工作的。非常感谢!
您的示例中的一个问题是您每次要验证密码时都使用新盐,而不是使用旧盐。实际上,您需要存储用于散列密码的盐以验证密码。
试试下面的代码:
$salt = Salt::random(12);
$password = Hashing::create_hash('123456', $salt);
验证:
if (Hashing::validate('123456', $password, $salt)) {
echo true;
} else {
echo false;
}
当然,每次要散列新密码时都需要生成一个新盐。
你的代码有很多问题,所以我强烈建议使用函数password_hash() and 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, 'a$' . $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 的教程。
如果你真的想让你的生活更轻松。你可以去 PHPASS
图书馆,它提供你使用的功能。您只需要创建一个 class 的对象并使用这些函数。
查看这些链接:
你可以从这里下载库:
Download PHPASS
您可以从这里获得更多信息:
Sample usage of the library
我想使用 salt 和 hash 来创建安全登录。我尝试遵循 this tutorial 并编写自己的代码,但它总是 return 错误。这是我的代码:
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 = 'a$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, 'a$' . $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;
}
}
请查收帮帮我!我不知道哪里出了问题以及它是如何工作的。非常感谢!
您的示例中的一个问题是您每次要验证密码时都使用新盐,而不是使用旧盐。实际上,您需要存储用于散列密码的盐以验证密码。
试试下面的代码:
$salt = Salt::random(12);
$password = Hashing::create_hash('123456', $salt);
验证:
if (Hashing::validate('123456', $password, $salt)) {
echo true;
} else {
echo false;
}
当然,每次要散列新密码时都需要生成一个新盐。
你的代码有很多问题,所以我强烈建议使用函数password_hash() and 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, 'a$' . $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 的教程。
如果你真的想让你的生活更轻松。你可以去 PHPASS
图书馆,它提供你使用的功能。您只需要创建一个 class 的对象并使用这些函数。
查看这些链接: 你可以从这里下载库: Download PHPASS
您可以从这里获得更多信息: Sample usage of the library