mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 12:32:08 +02:00
MDL-50860 core: improve creation of random strings
This commit is contained in:
parent
d89dc6daa5
commit
e4ac3879c2
@ -7558,14 +7558,16 @@ function count_letters($string) {
|
||||
* @param int $length The length of the string to be created.
|
||||
* @return string
|
||||
*/
|
||||
function random_string ($length=15) {
|
||||
function random_string($length=15) {
|
||||
$randombytes = random_bytes_emulate($length);
|
||||
$pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$pool .= 'abcdefghijklmnopqrstuvwxyz';
|
||||
$pool .= '0123456789';
|
||||
$poollen = strlen($pool);
|
||||
$string = '';
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$string .= substr($pool, (mt_rand()%($poollen)), 1);
|
||||
$rand = ord($randombytes[$i]);
|
||||
$string .= substr($pool, ($rand%($poollen)), 1);
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
@ -7586,13 +7588,56 @@ function complex_random_string($length=null) {
|
||||
if ($length===null) {
|
||||
$length = floor(rand(24, 32));
|
||||
}
|
||||
$randombytes = random_bytes_emulate($length);
|
||||
$string = '';
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$string .= $pool[(mt_rand()%$poollen)];
|
||||
$rand = ord($randombytes[$i]);
|
||||
$string .= $pool[($rand%$poollen)];
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to generates cryptographically secure pseudo-random bytes.
|
||||
*
|
||||
* Note this is achieved by fallbacking between:
|
||||
* - PHP 7 random_bytes().
|
||||
* - OpenSSL openssl_random_pseudo_bytes().
|
||||
* - In house random generator getting its entropy from various, hard to guess, pseudo-random sources.
|
||||
*
|
||||
* @param int $length requested length in bytes
|
||||
* @return string binary data
|
||||
*/
|
||||
function random_bytes_emulate($length) {
|
||||
global $CFG;
|
||||
if ($length <= 0) {
|
||||
debugging('Invalid random bytes length', DEBUG_DEVELOPER);
|
||||
return '';
|
||||
}
|
||||
if (function_exists('random_bytes')) {
|
||||
// Use PHP 7 goodness.
|
||||
$hash = @random_bytes($length);
|
||||
if ($hash !== false) {
|
||||
return $hash;
|
||||
}
|
||||
}
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
// For PHP 5.3 and later with openssl extension.
|
||||
$hash = openssl_random_pseudo_bytes($length);
|
||||
if ($hash !== false) {
|
||||
return $hash;
|
||||
}
|
||||
}
|
||||
|
||||
// Bad luck, there is no reliable random generator, let's just hash some unique stuff that is hard to guess.
|
||||
$hash = sha1(serialize($CFG) . serialize($_SERVER) . microtime(true) . uniqid('', true), true);
|
||||
// NOTE: the last param in sha1() is true, this means we are getting 20 bytes, not 40 chars as usual.
|
||||
if ($length <= 20) {
|
||||
return substr($hash, 0, $length);
|
||||
}
|
||||
return $hash . random_bytes_emulate($length - 20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given some text (which may contain HTML) and an ideal length,
|
||||
* this function truncates the text neatly on a word boundary if possible
|
||||
|
@ -2906,4 +2906,100 @@ class core_moodlelib_testcase extends advanced_testcase {
|
||||
$_SERVER['HTTP_X_FORWARDED_FOR'] = $xforwardedfor;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Test emulation of random_bytes() function.
|
||||
*/
|
||||
public function test_random_bytes_emulate() {
|
||||
$result = random_bytes_emulate(10);
|
||||
$this->assertSame(10, strlen($result));
|
||||
$this->assertnotSame($result, random_bytes_emulate(10));
|
||||
|
||||
$result = random_bytes_emulate(21);
|
||||
$this->assertSame(21, strlen($result));
|
||||
$this->assertnotSame($result, random_bytes_emulate(21));
|
||||
|
||||
$result = random_bytes_emulate(666);
|
||||
$this->assertSame(666, strlen($result));
|
||||
|
||||
$this->assertDebuggingNotCalled();
|
||||
|
||||
$result = random_bytes_emulate(0);
|
||||
$this->assertSame('', $result);
|
||||
$this->assertDebuggingCalled();
|
||||
|
||||
$result = random_bytes_emulate(-1);
|
||||
$this->assertSame('', $result);
|
||||
$this->assertDebuggingCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test function for creation of random strings.
|
||||
*/
|
||||
public function test_random_string() {
|
||||
$pool = 'a-zA-Z0-9';
|
||||
|
||||
$result = random_string(10);
|
||||
$this->assertSame(10, strlen($result));
|
||||
$this->assertRegExp('/^[' . $pool . ']+$/', $result);
|
||||
$this->assertNotSame($result, random_string(10));
|
||||
|
||||
$result = random_string(21);
|
||||
$this->assertSame(21, strlen($result));
|
||||
$this->assertRegExp('/^[' . $pool . ']+$/', $result);
|
||||
$this->assertNotSame($result, random_string(21));
|
||||
|
||||
$result = random_string(666);
|
||||
$this->assertSame(666, strlen($result));
|
||||
$this->assertRegExp('/^[' . $pool . ']+$/', $result);
|
||||
|
||||
$result = random_string();
|
||||
$this->assertSame(15, strlen($result));
|
||||
$this->assertRegExp('/^[' . $pool . ']+$/', $result);
|
||||
|
||||
$this->assertDebuggingNotCalled();
|
||||
|
||||
$result = random_string(0);
|
||||
$this->assertSame('', $result);
|
||||
$this->assertDebuggingCalled();
|
||||
|
||||
$result = random_string(-1);
|
||||
$this->assertSame('', $result);
|
||||
$this->assertDebuggingCalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test function for creation of complex random strings.
|
||||
*/
|
||||
public function test_complex_random_string() {
|
||||
$pool = preg_quote('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#%^&*()_+-=[];,./<>?:{} ', '/');
|
||||
|
||||
$result = complex_random_string(10);
|
||||
$this->assertSame(10, strlen($result));
|
||||
$this->assertRegExp('/^[' . $pool . ']+$/', $result);
|
||||
$this->assertNotSame($result, complex_random_string(10));
|
||||
|
||||
$result = complex_random_string(21);
|
||||
$this->assertSame(21, strlen($result));
|
||||
$this->assertRegExp('/^[' . $pool . ']+$/', $result);
|
||||
$this->assertNotSame($result, complex_random_string(21));
|
||||
|
||||
$result = complex_random_string(666);
|
||||
$this->assertSame(666, strlen($result));
|
||||
$this->assertRegExp('/^[' . $pool . ']+$/', $result);
|
||||
|
||||
$result = complex_random_string();
|
||||
$this->assertEquals(28, strlen($result), '', 4); // Expected length is 24 - 32.
|
||||
$this->assertRegExp('/^[' . $pool . ']+$/', $result);
|
||||
|
||||
$this->assertDebuggingNotCalled();
|
||||
|
||||
$result = complex_random_string(0);
|
||||
$this->assertSame('', $result);
|
||||
$this->assertDebuggingCalled();
|
||||
|
||||
$result = complex_random_string(-1);
|
||||
$this->assertSame('', $result);
|
||||
$this->assertDebuggingCalled();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user