mirror of
https://github.com/yiisoft/yii.git
synced 2026-02-20 01:21:22 +01:00
CSecurityManager:
1. Added /dev/urandom usage. 2. A couple of minor code optimizations.
This commit is contained in:
2
UPGRADE
2
UPGRADE
@@ -70,7 +70,7 @@ Upgrading from v1.1.13
|
||||
from both these to `CActiveRelation`.
|
||||
|
||||
- CSecurityManager::generateRandomKey() has been deprecated in favor of CSecurityManager::generateRandomString().
|
||||
Try not to use and avoid CSecurityManager::generateRandomKey() method anymore in your code.
|
||||
Try not to use anymore and avoid CSecurityManager::generateRandomKey() method in your code.
|
||||
|
||||
Upgrading from v1.1.12
|
||||
----------------------
|
||||
|
||||
@@ -102,7 +102,10 @@ class CSecurityManager extends CApplicationComponent
|
||||
$this->setValidationKey($key);
|
||||
else
|
||||
{
|
||||
$key=$this->generateRandomString(32);
|
||||
if(($key=$this->generateRandomString(32,true))===false)
|
||||
if(($key=$this->generateRandomString(32,false))===false)
|
||||
throw new CException(Yii::t('yii',
|
||||
'CSecurityManager::generateRandomString() cannot generate random string in the current environment.'));
|
||||
$this->setValidationKey($key);
|
||||
Yii::app()->setGlobalState(self::STATE_VALIDATION_KEY,$key);
|
||||
}
|
||||
@@ -136,7 +139,10 @@ class CSecurityManager extends CApplicationComponent
|
||||
$this->setEncryptionKey($key);
|
||||
else
|
||||
{
|
||||
$key=$this->generateRandomString(32);
|
||||
if(($key=$this->generateRandomString(32,true))===false)
|
||||
if(($key=$this->generateRandomString(32,false))===false)
|
||||
throw new CException(Yii::t('yii',
|
||||
'CSecurityManager::generateRandomString() cannot generate random string in the current environment.'));
|
||||
$this->setEncryptionKey($key);
|
||||
Yii::app()->setGlobalState(self::STATE_ENCRYPTION_KEY,$key);
|
||||
}
|
||||
@@ -324,20 +330,25 @@ class CSecurityManager extends CApplicationComponent
|
||||
* transparent in raw URL encoding.
|
||||
* @param integer $length of the string in characters to be generated.
|
||||
* @param boolean $cryptographicallyStrong set this to require cryptographically strong randomness.
|
||||
* @return string generated random string.
|
||||
* @return string|boolean generated random string. Returns false in case string cannot be generated
|
||||
*/
|
||||
public function generateRandomString($length,$cryptographicallyStrong=true)
|
||||
{
|
||||
return strtr(
|
||||
$this->substr(base64_encode($this->generateRandomBytes($length+2,$cryptographicallyStrong)),0,$length),
|
||||
array('+'=>'_','/'=>'~')
|
||||
);
|
||||
if(($randomBytes=$this->generateRandomBytes($length+2,$cryptographicallyStrong))!==false)
|
||||
{
|
||||
return strtr($this->substr(base64_encode($randomBytes),0,$length),array('+'=>'_','/'=>'~'));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string of random bytes.
|
||||
* @param integer $length number of random bytes to be generated.
|
||||
* @param boolean $cryptographicallyStrong whether generated string should be cryptographically strong.
|
||||
* True parameter value may cause very slow random generation.
|
||||
* @return boolean|string generated random binary string. Returns false on failure.
|
||||
*/
|
||||
public function generateRandomBytes($length,$cryptographicallyStrong=true)
|
||||
@@ -360,7 +371,7 @@ class CSecurityManager extends CApplicationComponent
|
||||
return $this->substr($bytes,0,$length);
|
||||
}
|
||||
|
||||
if(($file=@fopen('/dev/random','r'))!==false &&
|
||||
if(($file=@fopen('/dev/random','rb'))!==false &&
|
||||
stream_set_blocking($file,0) &&
|
||||
($bytes=@fread($file,$length))!==false &&
|
||||
(fclose($file) || true) &&
|
||||
@@ -371,7 +382,7 @@ class CSecurityManager extends CApplicationComponent
|
||||
|
||||
$i=0;
|
||||
while($this->strlen($bytes)<$length &&
|
||||
($byte=$this->getSessionRandomBlock())!==false &&
|
||||
($byte=$this->generateSessionRandomBlock())!==false &&
|
||||
++$i<3)
|
||||
{
|
||||
$bytes.=$byte;
|
||||
@@ -382,6 +393,15 @@ class CSecurityManager extends CApplicationComponent
|
||||
return false;
|
||||
}
|
||||
|
||||
if(($file=@fopen('/dev/urandom','rb'))!==false &&
|
||||
stream_set_blocking($file,0) &&
|
||||
($bytes=@fread($file,$length))!==false &&
|
||||
(fclose($file) || true) &&
|
||||
$this->strlen($bytes)>=$length)
|
||||
{
|
||||
return $this->substr($bytes,0,$length);
|
||||
}
|
||||
|
||||
while($this->strlen($bytes)<$length)
|
||||
$bytes.=$this->generatePseudoRandomBlock();
|
||||
return $this->substr($bytes,0,$length);
|
||||
@@ -394,32 +414,26 @@ class CSecurityManager extends CApplicationComponent
|
||||
*/
|
||||
public function generatePseudoRandomBlock()
|
||||
{
|
||||
$r=array();
|
||||
$bytes='';
|
||||
for($i=0; $i<32; ++$i)
|
||||
$r[]=pack('S',mt_rand(0,0xffff));
|
||||
$bytes.=pack('S',mt_rand(0,0xffff));
|
||||
|
||||
// On UNIX and UNIX-like operating systems the numerical values in `ps`, `uptime` and `iostat`
|
||||
// ought to be fairly unpredictable. Gather the non-zero digits from those.
|
||||
foreach(array('ps','uptime','iostat') as $command) {
|
||||
@exec($command,$s,$ret);
|
||||
if(is_array($s) && !empty($s) && $ret===0)
|
||||
{
|
||||
foreach($s as $v)
|
||||
{
|
||||
if(preg_match_all('/[1-9]+/',$v,$m)!==false && isset($m[0]))
|
||||
$r[]=implode('',$m[0]);
|
||||
}
|
||||
}
|
||||
@exec($command,$commandResult,$retVal);
|
||||
if(is_array($commandResult) && !empty($commandResult) && $retVal==0)
|
||||
$bytes.=preg_replace('/[^1-9]/','',implode('',$commandResult));
|
||||
}
|
||||
|
||||
// Gather the current time's microsecond part. Note: this is only a source of entropy on
|
||||
// the first call! If multiple calls are made, the entropy is only as much as the
|
||||
// randomness in the time between calls.
|
||||
$r[]=$this->substr(microtime(),2,6);
|
||||
$bytes.=$this->substr(microtime(),2,6);
|
||||
|
||||
// Concatenate everything gathered, mix it with sha512. hash() is part of PHP core and
|
||||
// enabled by default but it can be disabled at compile time but we ignore that possibility here.
|
||||
return hash('sha512',implode('',$r),true);
|
||||
return hash('sha512',$bytes,true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -427,7 +441,7 @@ class CSecurityManager extends CApplicationComponent
|
||||
* @return boolean|string 20-byte random binary string or false on error.
|
||||
* Returns false in case it cannot be retrieved.
|
||||
*/
|
||||
public function getSessionRandomBlock()
|
||||
public function generateSessionRandomBlock()
|
||||
{
|
||||
ini_set('session.entropy_length',20);
|
||||
if(ini_get('session.entropy_length')!=20)
|
||||
|
||||
@@ -185,7 +185,7 @@ class CPasswordHelper
|
||||
if($cost<4 || $cost>31)
|
||||
throw new CException(Yii::t('yii','{class}::$cost must be between 4 and 31.',array('{class}'=>__CLASS__)));
|
||||
|
||||
$random=Yii::app()->getSecurityManager()->generateRandomString(20);
|
||||
$random=Yii::app()->getComponent('securityManager')->generateRandomString(20);
|
||||
return sprintf('$2a$%02d$',$cost).str_replace('+','.',substr(base64_encode($random),0,22));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user