duandang9434
duandang9434
2015-05-08 04:08

如何在登录时使用salt和hash?

已采纳

I want to use salt and hash to create security login. I try to follow this tutorial and write own code but it always return false. Here is my code:

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;
}

And two classes I included:

<?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;
    }

}

Please check help me! I don't know where is wrong and how it works. Thank so much!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

3条回答

  • doudeng9425 doudeng9425 6年前

    There are many problems with your code, so i strongly suggest to use the functions password_hash() and password_verify() to do the hashing.

    Because you said that you want to understand how it works, here some tips:

    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);
    }
    

    This method first tries to use crypt() which is good, because it generates a BCrypt hash. The cost parameter will fail if it is smaller than 10, and the salt can be generated unsafe, and it uses ways too much entropy from the pool. Then it checks whether the hash() functions exists but this function is not at all made to hash passwords and has nothing to do with crypt().

    Later for verification you do not use crypt(), instead you check with the hash() function, this is a different algorithm as before. Then the salt cannot be choosen freely to verify a password, instead you need the same salt that was used to generate the hash, the crypt() function actually did include this salt in the hash-value.

    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));
    }
    

    If you want to learn a bit more about password hashing, i would invite you to read my tutorial about secure password storing.

    点赞 评论 复制链接分享
  • dongxiang5879 dongxiang5879 6年前

    If you really want to make your life easier. You can go for PHPASS library which provides you functions to use. You just need to create an object of the class and use the functions.

    Check out these links: You can download the library from here: Download PHPASS

    You can get some more info from here: Sample usage of the library

    点赞 评论 复制链接分享
  • doupaoshu8334 doupaoshu8334 6年前

    One problem in your example is that you use a new salt every time you want to verify a password, instead of using the old salt. In practice, you need to store the salt you used to hash a password in order to verify it.

    Try the following code:

    $salt = Salt::random(12);
    $password = Hashing::create_hash('123456', $salt);
    

    To verify:

    if (Hashing::validate('123456', $password, $salt)) {
        echo true;
    } else {
        echo false;
    }
    

    Of course you will need to generate a NEW salt every time you want to hash a NEW password.

    点赞 评论 复制链接分享

相关推荐