如何在登录中使用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