2013-05-11 94 views
0

我正在使用Bcrypt與php來獲得一個安全的散列密碼提交到數據庫 在註冊時密碼被哈希但在登錄系統顯示2密碼不是匹配任何人都可以幫助我????????使用Bcrypt與phpto散列密碼不工作

我剛剛從password.php文件

  • 的password_hash功能
  • password_verify功能

password.php

<?php 
/** 
* A Compatibility library with PHP 5.5's simplified password hashing API. 
* 
* @author Anthony Ferrara <[email protected]> 
* @license http://www.opensource.org/licenses/mit-license.html MIT License 
* @copyright 2012 The Authors 
*/ 

if (!defined('PASSWORD_DEFAULT')) { 

    define('PASSWORD_BCRYPT', 1); 
    define('PASSWORD_DEFAULT', PASSWORD_BCRYPT); 

    /** 
    * Hash the password using the specified algorithm 
    * 
    * @param string $password The password to hash 
    * @param int $algo  The algorithm to use (Defined by PASSWORD_* constants) 
    * @param array $options The options for the algorithm to use 
    * 
    * @return string|false The hashed password, or false on error. 
    */ 
    function password_hash($password, $algo, array $options = array()) { 
     if (!function_exists('crypt')) { 
      trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING); 
      return null; 
     } 
     if (!is_string($password)) { 
      trigger_error("password_hash(): Password must be a string", E_USER_WARNING); 
      return null; 
     } 
     if (!is_int($algo)) { 
      trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING); 
      return null; 
     } 
     switch ($algo) { 
      case PASSWORD_BCRYPT: 
       // Note that this is a C constant, but not exposed to PHP, so we don't define it here. 
       $cost = 10; 
       if (isset($options['cost'])) { 
        $cost = $options['cost']; 
        if ($cost < 4 || $cost > 31) { 
         trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING); 
         return null; 
        } 
       } 
       // The length of salt to generate 
       $raw_salt_len = 16; 
       // The length required in the final serialization 
       $required_salt_len = 22; 
       $hash_format = sprintf("$2y$%02d$", $cost); 
       break; 
      default: 
       trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING); 
       return null; 
     } 
     if (isset($options['salt'])) { 
      switch (gettype($options['salt'])) { 
       case 'NULL': 
       case 'boolean': 
       case 'integer': 
       case 'double': 
       case 'string': 
        $salt = (string) $options['salt']; 
        break; 
       case 'object': 
        if (method_exists($options['salt'], '__tostring')) { 
         $salt = (string) $options['salt']; 
         break; 
        } 
       case 'array': 
       case 'resource': 
       default: 
        trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING); 
        return null; 
      } 
      if (strlen($salt) < $required_salt_len) { 
       trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", strlen($salt), $required_salt_len), E_USER_WARNING); 
       return null; 
      } elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) { 
       $salt = str_replace('+', '.', base64_encode($salt)); 
      } 
     } else { 
      $buffer = ''; 
      $buffer_valid = false; 
      if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) { 
       $buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM); 
       if ($buffer) { 
        $buffer_valid = true; 
       } 
      } 
      if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) { 
       $buffer = openssl_random_pseudo_bytes($raw_salt_len); 
       if ($buffer) { 
        $buffer_valid = true; 
       } 
      } 
      if (!$buffer_valid && is_readable('/dev/urandom')) { 
       $f = fopen('/dev/urandom', 'r'); 
       $read = strlen($buffer); 
       while ($read < $raw_salt_len) { 
        $buffer .= fread($f, $raw_salt_len - $read); 
        $read = strlen($buffer); 
       } 
       fclose($f); 
       if ($read >= $raw_salt_len) { 
        $buffer_valid = true; 
       } 
      } 
      if (!$buffer_valid || strlen($buffer) < $raw_salt_len) { 
       $bl = strlen($buffer); 
       for ($i = 0; $i < $raw_salt_len; $i++) { 
        if ($i < $bl) { 
         $buffer[$i] = $buffer[$i]^chr(mt_rand(0, 255)); 
        } else { 
         $buffer .= chr(mt_rand(0, 255)); 
        } 
       } 
      } 
      $salt = str_replace('+', '.', base64_encode($buffer)); 
     } 
     $salt = substr($salt, 0, $required_salt_len); 

     $hash = $hash_format . $salt; 

     $ret = crypt($password, $hash); 

     if (!is_string($ret) || strlen($ret) <= 13) { 
      return false; 
     } 

     return $ret; 
    } 

    /** 
    * Get information about the password hash. Returns an array of the information 
    * that was used to generate the password hash. 
    * 
    * array(
    * 'algo' => 1, 
    * 'algoName' => 'bcrypt', 
    * 'options' => array(
    *  'cost' => 10, 
    * ), 
    *) 
    * 
    * @param string $hash The password hash to extract info from 
    * 
    * @return array The array of information about the hash. 
    */ 
    function password_get_info($hash) { 
     $return = array(
      'algo' => 0, 
      'algoName' => 'unknown', 
      'options' => array(), 
     ); 
     if (substr($hash, 0, 4) == '$2y$' && strlen($hash) == 60) { 
      $return['algo'] = PASSWORD_BCRYPT; 
      $return['algoName'] = 'bcrypt'; 
      list($cost) = sscanf($hash, "$2y$%d$"); 
      $return['options']['cost'] = $cost; 
     } 
     return $return; 
    } 

    /** 
    * Determine if the password hash needs to be rehashed according to the options provided 
    * 
    * If the answer is true, after validating the password using password_verify, rehash it. 
    * 
    * @param string $hash The hash to test 
    * @param int $algo The algorithm used for new password hashes 
    * @param array $options The options array passed to password_hash 
    * 
    * @return boolean True if the password needs to be rehashed. 
    */ 
    function password_needs_rehash($hash, $algo, array $options = array()) { 
     $info = password_get_info($hash); 
     if ($info['algo'] != $algo) { 
      return true; 
     } 
     switch ($algo) { 
      case PASSWORD_BCRYPT: 
       $cost = isset($options['cost']) ? $options['cost'] : 10; 
       if ($cost != $info['options']['cost']) { 
        return true; 
       } 
       break; 
     } 
     return false; 
    } 

    /** 
    * Verify a password against a hash using a timing attack resistant approach 
    * 
    * @param string $password The password to verify 
    * @param string $hash  The hash to verify against 
    * 
    * @return boolean If the password matches the hash 
    */ 
    function password_verify($password, $hash) { 
     if (!function_exists('crypt')) { 
      trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING); 
      return false; 
     } 
     $ret = crypt($password, $hash); 
     if (!is_string($ret) || strlen($ret) != strlen($hash) || strlen($ret) <= 13) { 
      return false; 
     } 

     $status = 0; 
     for ($i = 0; $i < strlen($ret); $i++) { 
      $status |= (ord($ret[$i])^ord($hash[$i])); 
     } 

     return $status === 0; 
    } 
} 

register.php需要

require_once('include/password.php'); 

    $hash = password_hash($pass1, PASSWORD_BCRYPT); 
    if(password_verify($pass1, $hash)) 
    { 
     echo "matched"; 
    } 
    echo "do not match"; 

//************Insert all the user's input to the database**************************// 
     $query = mysql_query("INSERT INTO user(user_name, first_name, last_name, governorate, district, village, birth_date, email_address, specialization, password, registered_date)VALUES('$username', '$firstname', '$lastname', '$governorate', '$district', '$village', '$bdate', '$email', '$specialization', '$hash', now())")or die("could not insert data"); 

的login.php

//***********for hashing password***************************// 

require_once('include/password.php'); 

    $hash = password_hash($pass, PASSWORD_BCRYPT); 
    if(password_verify($pass, $hash)) 
    { 
     echo "matched"; 
    } 
    echo $hash; 

$sql=mysql_query("SELECT user_id, email_address, first_name, user_name FROM user WHERE email_address='$email'AND password= '$hash' LIMIT 1") or die("error in user table"); 
$login_check = mysql_num_rows($sql); 

回答

2

你做錯了。

創建新帳戶時,您將獲得用戶的密碼。您將其散列並將該散列存儲到數據庫中。此時不需要檢查密碼是否與散列相匹配。

寄存器

require_once('include/password.php'); 

$hash = password_hash($pass1, PASSWORD_BCRYPT); 

//************Insert all the user's input to the database**************************// 
$query = mysql_query("INSERT INTO user (user_name, .... password, registered_date) VALUES('".mysql_real_escape_string($username)."', ... '".mysql_real_escape_string($hash)."', now())") or die("could not insert data"); 

請永遠不要忘記將它們放入一個查詢字符串時逃脫所有字符串。我在上面的例子中爲你添加了這個。

當檢查在登錄的密碼,您從數據庫中讀取的哈希,並呼籲從登錄表單與此哈希驗證功能和當前給定的密碼:

登錄

require_once('include/password.php'); 

$sql=mysql_query("SELECT user_id, ... password FROM user WHERE email_address='".mysql_real_escape_string($email)."'") or die("error in user table"); 

$error = false; 
if (mysql_num_rows($sql) == 0) { $error = true; // user not found - don't tell anyone this detail! } 
if (mysql_num_rows($sql) > 1) { $error = true; // email addresses are not unique in your database - this should not happen!} 
if (!$error) { 
    $user = mysql_fetch_assoc($sql); 
    if (password_verify($pass, $user['password']) { 
     $login=true; 
    } else { 
     $error = true; // Password is wrong - don't tell anyone this detail! 
    } 
} 

這並不難,只要看一下文檔:https://github.com/ircmaxell/password_compat

雖然你在這樣做:在實現重新哈希時很少有開銷的密碼。

+0

應該注意的是,此處使用的轉義函數('mysql_real_escape_string')已被該庫的其餘部分棄用。改爲使用「mysqli」和「mysqli_real_escape_string」。 – Carcigenicate 2016-01-31 01:12:13

+0

雖然你完全瞭解了'mysql'擴展名的一般主題,你可能已經知道這個命令是從3年前開始的 - 並且注意只有將'mysql_real_escape_string'改爲'mysqli_real_escape_string'還不夠,你必須將所有'mysql_ *'函數更改爲他們的'mysqli_ *'副本。然而,這需要更多的字符來描述,而不是納入SO評論部分。 – Sven 2016-02-01 00:23:20

+1

我知道這是舊的,這就是爲什麼我沒有downvote。這只是一個閱讀此文的人指點他們的更新功能。不尊重你的回答。 – Carcigenicate 2016-02-01 00:24:40