crypt()为什么产生不同的结果?

问题描述:

隐窝正在产生不同的散列以相同的输入数据,并且将[以下]先前官能散列发生器/检查不再工作用于认证用户:crypt()为什么产生不同的结果?

public static function blowfish($password, $storedpass = false) { 
    //if encrypted data is passed, check it against input ($info) 
     if ($storedpass) { 
      if (substr($storedpass, 0, 60) == crypt($password, "$2y$08$".substr($storedpass, 60))) { 
       return true; 
      } else { 
       return false; 
      } 
     } else { 
      //make a salt and hash it with input, and add salt to end 
      $salt = ""; 
      for ($i = 0; $i < 22; $i++) { 
      $salt .= substr("./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", mt_rand(0, 63), 1); 
      } 
      //return 82 char string (60 char hash & 22 char salt) 
      return crypt($password, "$2y$08$".$salt).$salt; 
    } 
} 

我撞我的头靠在墙上,并有Zend的内部算法与PHP与操作系统算法之间的差异没有找到答案;或PHP之间的差异5.3.8 VS前面...

编辑:我的问题是技术上的回答,这是我的错,我没有正确问。我实施了:

$salt = substr(bin2hex(openssl_random_pseudo_bytes(22)), 0, 22); 
      //for ($i = 0; $i < 22; $i++) { 
      //$salt .= substr("./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", mt_rand(0, 63), 1); 
      //} 

我真正的问题是;为什么以下函数返回不同?

print(substr($storedpass, 0, 60)."<br />"); 

回报:$ 2Y $ 08 $ 43f053b1538df81054d4cOJyrO5/j7NtZBCw6LrFof29cLBs7giK6

print(crypt($password, "$2a$08$".substr($storedpass, 60))); 

回报:$ 2A $ 08 $ 43f053b1538df81054d4cOPSGh/LMc0PZx6RC6PlXOSc61BKq/F6。

+0

一点题外话:使用加密PRNG生成盐,而不是一个严重播种Mersenne扭曲 – CodesInChaos 2012-08-15 17:31:15

+0

@CodesInChaos不够公平,用什么最好的[PHP]函数呢? mt_rand()? – KneeSkrap3r 2012-08-15 17:41:21

+0

我不是一个PHP开发,但'mcrypt_create_iv(大小,MCRYPT_DEV_URANDOM)'可能是一个不错的选择。或者你可以从'的/ dev/urandom'在Linux http://*.com/a/1551064/445517或直接读取['openssl_random_pseudo_bytes'](http://php.net/manual/en/function.openssl-随机伪bytes.php)后进一步研究 – CodesInChaos 2012-08-15 18:07:17

因为要创建的salt与随机数的帮助下,

功能mt_rand()会当你打电话,任选最小值,最大值参数每次创建随机数。通常对于强密码学密码散列,Salt应该使用密码安全伪随机数发生器(CSPRNG)生成。

然后来到你的问题,我认为还会有Zend和PHP之间的算法没有差别。因为zend是一个围绕核心php的框架,并且使用它。

要验证密码,crypt检查工作是如何

crypt($password, $stored_hash) == $stored_hash; 

一旦你,当你第一次哈希存储的散列,它会很容易通过这个来验证。

这就是实际发生在这里,如果你通过哈希作为第二个参数的功能河豚,它会通过一个布尔值返回验证,不管盐。

if (substr($storedpass, 0, 60) == crypt($password, "$2y$08$".substr($storedpass, 60))) { 
    return true; 
} else { 
    return false; 
} 

你对散列和安全信息,请阅读this

希望这有助于

+0

我猜代码最初“工作”,因为在较旧版本的PHP中,'mt_rand'背后的PRNG没有自动播种。 – CodesInChaos 2012-08-15 18:15:46

+0

@CodesInChaos当然是。 – 2012-08-15 18:18:52

+0

所以你们都说使用CSPRNG而不是我的mt_rand应该可以工作?我实现了$ salt = bin2hex(openssl_random_pseudo_bytes(22)),并且遇到同样的问题... – KneeSkrap3r 2012-08-15 19:35:29