%PDF- %PDF-
| Direktori : /home1/lightco1/www/administrator/components/com_akeeba/BackupEngine/Util/ |
| Current File : //home1/lightco1/www/administrator/components/com_akeeba/BackupEngine/Util/RandomValue.php |
<?php
/**
* Akeeba Engine
* The modular PHP5 site backup engine
* @copyright Copyright (c)2006-2017 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU GPL version 3 or, at your option, any later version
* @package akeebaengine
*/
namespace Akeeba\Engine\Util;
// Protection against direct access
defined('AKEEBAENGINE') or die();
/**
* Crypto-safe random value generator. Based on the Randval class of the Aura for PHP's Session package.
* The following is the license file accompanying the original file.
*
* ********************************************************************************
* Copyright (c) 2011-2016, Aura for PHP
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ********************************************************************************
*
* Please note that this is a MODIFIED copy of the Randval class, mainly to allow it to be used on hosts
* which lack both mbcrypt and OpenSSL PHP modules.
*/
class RandomValue
{
/**
*
* Returns a cryptographically secure random value.
*
* @param integer $bytes How many bytes to return
*
* @return string
*/
public function generate($bytes = 32)
{
if (function_exists('extension_loaded') && function_exists('openssl_random_pseudo_bytes'))
{
defined('IS_WIN') or define('IS_WIN', DIRECTORY_SEPARATOR == '\\');
if (extension_loaded('openssl') && (version_compare(PHP_VERSION, '5.3.4') >= 0 || IS_WIN))
{
$strong = false;
$randBytes = openssl_random_pseudo_bytes($bytes, $strong);
if ($strong)
{
return $randBytes;
}
}
}
if (function_exists('extension_loaded') && function_exists('mcrypt_create_iv'))
{
if (extension_loaded('mcrypt'))
{
return mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
}
}
return $this->genRandomBytes($bytes);
}
/**
* Generates a random string with the specified length. WARNING: You get to specify the number of
* random characters in the string, not the number of random bytes. The character pool is 64 characters
* (6 bits) long. The entropy of your string is 6 * $characters bits. This means that a random string
* of 32 characters has an entropy of 192 bits whereas a random sequence of 32 bytes returned by generate()
* has an entropy of 8 * 32 = 256 bits.
*
* @param int $characters
*
* @return string
*/
public function generateString($characters = 32)
{
$sourceString = str_split('abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789', 1);
$ret = '';
$bytes = ceil($characters / 4) * 3;
$randBytes = $this->generate($bytes);
for ($i = 0; $i < $bytes; $i += 3)
{
$subBytes = substr($randBytes, $i, 3);
$subBytes = str_split($subBytes, 1);
$subBytes = ord($subBytes[0]) * 65536 + ord($subBytes[1]) * 256 + ord($subBytes[2]);
$subBytes = $subBytes & bindec('00000000111111111111111111111111');
$b = array();
$b[0] = $subBytes >> 18;
$b[1] = ($subBytes >> 12) & bindec('111111');
$b[2] = ($subBytes >> 6) & bindec('111111');
$b[3] = $subBytes & bindec('111111');
$ret .= $sourceString[$b[0]] . $sourceString[$b[1]] . $sourceString[$b[2]] . $sourceString[$b[3]];
}
return substr($ret, 0, $characters);
}
/**
* Generate random bytes. Adapted from Joomla! 3.2.
*
* @param integer $length Length of the random data to generate
*
* @return string Random binary data
*/
protected function genRandomBytes($length = 32)
{
$length = (int) $length;
$sslStr = '';
/*
* Collect any entropy available in the system along with a number
* of time measurements of operating system randomness.
*/
$bitsPerRound = 2;
$maxTimeMicro = 400;
$shaHashLength = 20;
$randomStr = '';
$total = $length;
// Check if we can use /dev/urandom.
$urandom = false;
$handle = null;
// This is PHP 5.3.3 and up
if (function_exists('stream_set_read_buffer') && @is_readable('/dev/urandom'))
{
$handle = @fopen('/dev/urandom', 'rb');
if ($handle)
{
$urandom = true;
}
}
while ($length > strlen($randomStr))
{
$bytes = ($total > $shaHashLength)? $shaHashLength : $total;
$total -= $bytes;
/*
* Collect any entropy available from the PHP system and filesystem.
* If we have ssl data that isn't strong, we use it once.
*/
$entropy = rand() . uniqid(mt_rand(), true) . $sslStr;
$entropy .= implode('', @fstat(fopen(__FILE__, 'r')));
$entropy .= memory_get_usage();
$sslStr = '';
if ($urandom)
{
stream_set_read_buffer($handle, 0);
$entropy .= @fread($handle, $bytes);
}
else
{
/*
* There is no external source of entropy so we repeat calls
* to mt_rand until we are assured there's real randomness in
* the result.
*
* Measure the time that the operations will take on average.
*/
$samples = 3;
$duration = 0;
for ($pass = 0; $pass < $samples; ++$pass)
{
$microStart = microtime(true) * 1000000;
$hash = sha1(mt_rand(), true);
for ($count = 0; $count < 50; ++$count)
{
$hash = sha1($hash, true);
}
$microEnd = microtime(true) * 1000000;
$entropy .= $microStart . $microEnd;
if ($microStart >= $microEnd)
{
$microEnd += 1000000;
}
$duration += $microEnd - $microStart;
}
$duration = $duration / $samples;
/*
* Based on the average time, determine the total rounds so that
* the total running time is bounded to a reasonable number.
*/
$rounds = (int) (($maxTimeMicro / $duration) * 50);
/*
* Take additional measurements. On average we can expect
* at least $bitsPerRound bits of entropy from each measurement.
*/
$iter = $bytes * (int) ceil(8 / $bitsPerRound);
for ($pass = 0; $pass < $iter; ++$pass)
{
$microStart = microtime(true);
$hash = sha1(mt_rand(), true);
for ($count = 0; $count < $rounds; ++$count)
{
$hash = sha1($hash, true);
}
$entropy .= $microStart . microtime(true);
}
}
$randomStr .= sha1($entropy, true);
}
if ($urandom)
{
@fclose($handle);
}
return substr($randomStr, 0, $length);
}
}