Commit c2ece933 by Alexander Makarov

Merge pull request #4115 from yiisoft/security-adjustments

Added Security::generateRandomHexKey(), used it for various tokens and default key generation
parents 37dde677 481db355
...@@ -129,6 +129,7 @@ Yii Framework 2 Change Log ...@@ -129,6 +129,7 @@ Yii Framework 2 Change Log
- Added unit test for saving and loading data. - Added unit test for saving and loading data.
- Enh #4080: Added proper handling and support of the symlinked directories in `FileHelper`, added $options parameter in `FileHelper::removeDirectory()` (resurtm) - Enh #4080: Added proper handling and support of the symlinked directories in `FileHelper`, added $options parameter in `FileHelper::removeDirectory()` (resurtm)
- Enh #4086: changedAttributes of afterSave Event now contain old values (dizews) - Enh #4086: changedAttributes of afterSave Event now contain old values (dizews)
- Enh #4114: Added Security::generateRandomHexKey(), used it for various tokens and default key generation (samdark)
- Enh: Added support for using sub-queries when building a DB query with `IN` condition (qiangxue) - Enh: Added support for using sub-queries when building a DB query with `IN` condition (qiangxue)
- Enh: Supported adding a new response formatter without the need to reconfigure existing formatters (qiangxue) - Enh: Supported adding a new response formatter without the need to reconfigure existing formatters (qiangxue)
- Enh: Added `yii\web\UrlManager::addRules()` to simplify adding new URL rules (qiangxue) - Enh: Added `yii\web\UrlManager::addRules()` to simplify adding new URL rules (qiangxue)
......
...@@ -298,30 +298,46 @@ class Security extends Component ...@@ -298,30 +298,46 @@ class Security extends Component
} }
if (!isset($this->_keys[$name]) || $regenerate) { if (!isset($this->_keys[$name]) || $regenerate) {
$this->_keys[$name] = utf8_encode($this->generateRandomKey($length)); $this->_keys[$name] = $this->generateRandomKey($length);
file_put_contents($keyFile, json_encode($this->_keys)); file_put_contents($keyFile, json_encode($this->_keys));
} }
return utf8_decode($this->_keys[$name]); return $this->_keys[$name];
} }
/** /**
* Generates a random key. * Generates specified number of random bytes.
* Note the generated key is a binary string with the specified number of bytes in it. * Note that output may not be ASCII.
* @param integer $length the length of the key that should be generated * @see generateRandomKey() if you need a string.
*
* @param integer $length the number of bytes to generate
* @throws Exception on failure. * @throws Exception on failure.
* @return string the generated random key * @return string the generated random bytes
*/ */
public function generateRandomKey($length = 32) public function generateRandomBytes($length = 32)
{ {
if (!extension_loaded('mcrypt')) { if (!extension_loaded('mcrypt')) {
throw new InvalidConfigException('The mcrypt PHP extension is not installed.'); throw new InvalidConfigException('The mcrypt PHP extension is not installed.');
} }
$key = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); $bytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
if ($key === false) { if ($bytes === false) {
throw new Exception('Unable to generate random key.'); throw new Exception('Unable to generate random bytes.');
} }
return $key; return $bytes;
}
/**
* Generates a random string of specified length.
* The string generated matches [A-Za-z0-9_.-]+
*
* @param integer $length the length of the key in characters
* @throws Exception Exception on failure.
* @return string the generated random key
*/
public function generateRandomKey($length = 32)
{
$bytes = $this->generateRandomBytes($length);
return strtr(StringHelper::byteSubstr(base64_encode($bytes), 0, $length), '+/=', '_-.');
} }
/** /**
...@@ -456,7 +472,7 @@ class Security extends Component ...@@ -456,7 +472,7 @@ class Security extends Component
} }
// Get 20 * 8bits of random entropy // Get 20 * 8bits of random entropy
$rand = $this->generateRandomKey(20); $rand = $this->generateRandomBytes(20);
// Add the microtime for a little more entropy. // Add the microtime for a little more entropy.
$rand .= microtime(true); $rand .= microtime(true);
......
...@@ -132,10 +132,18 @@ class SecurityTest extends TestCase ...@@ -132,10 +132,18 @@ class SecurityTest extends TestCase
$this->assertEquals($data, $decryptedData); $this->assertEquals($data, $decryptedData);
} }
public function testGenerateRandomBytes()
{
$length = 21;
$key = $this->security->generateRandomBytes($length);
$this->assertEquals($length, strlen($key));
}
public function testGenerateRandomKey() public function testGenerateRandomKey()
{ {
$keyLength = 20; $length = 21;
$key = $this->security->generateRandomKey($keyLength); $key = $this->security->generateRandomKey($length);
$this->assertEquals($keyLength, strlen($key)); $this->assertEquals($length, strlen($key));
$this->assertEquals(1, preg_match('/[A-Za-z0-9_.-]+/', $key));
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment