rfc:improve_predictable_prng_random
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revisionNext revisionBoth sides next revision | ||
rfc:improve_predictable_prng_random [2017/02/01 01:43] – created yohgaki | rfc:improve_predictable_prng_random [2017/02/03 04:15] – Explicitly explain BC in PHP 7.1 yohgaki | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== PHP RFC: Improve predictable PRNG random ====== | + | ====== PHP RFC: Improve predictable PRNG random |
* Version: 0.9 | * Version: 0.9 | ||
* Date: 2017-02-01 | * Date: 2017-02-01 | ||
Line 14: | Line 14: | ||
<code php> | <code php> | ||
// We need the same random numbers here | // We need the same random numbers here | ||
- | mt_srand(1234); | + | srand(1234); |
for ($i=0; $i < 10; $i++) { | for ($i=0; $i < 10; $i++) { | ||
// Use my PRNG state | // Use my PRNG state | ||
- | | + | |
} | } | ||
Line 29: | Line 29: | ||
</ | </ | ||
- | **This is not limited to specific request that calls mt_srand($some_value), | + | **Above code worked as it should. PHP 7.1 broke this code.** Similarly, shuffle()/ |
+ | |||
+ | <code php> | ||
+ | // We need the same random numbers here | ||
+ | mt_srand(1234); | ||
+ | for ($i=0; $i < 10; $i++) { | ||
+ | // Use my PRNG state | ||
+ | | ||
+ | } | ||
+ | |||
+ | // Somewhere later in code AND/OR even other requests | ||
+ | |||
+ | // We need to shuffle randomly | ||
+ | shuffle($my_random_array); | ||
+ | </ | ||
+ | |||
+ | **These behaviors are not limited to specific request that calls mt_srand($some_value)/ | ||
PHP should have system and user PRNG state to resolve this behavior. | PHP should have system and user PRNG state to resolve this behavior. | ||
Line 48: | Line 64: | ||
===== Proposal ===== | ===== Proposal ===== | ||
- | ==== Return PRNG state object from mt_srand()/ | + | ==== Return PRNG random |
<code php> | <code php> | ||
- | | + | |
- | | + | |
</ | </ | ||
- | Returned RandomeState | + | mt_srand()/ |
Note: srand() is alias of mt_rand(). Python initializes MT rand state by string data like this proposal. | Note: srand() is alias of mt_rand(). Python initializes MT rand state by string data like this proposal. | ||
Line 79: | Line 95: | ||
When user initialized PRNG state object is specified, specified state is used to generate random values. | When user initialized PRNG state object is specified, specified state is used to generate random values. | ||
- | ==== RandomState | + | ==== Random |
+ | |||
+ | Create RandomeInterface, | ||
<code php> | <code php> | ||
- | class RandomState | + | |
+ | interface RandomInterface { | ||
+ | public function getInt(int $min = NULL, int $max = NULL); // Int random | ||
+ | public function getBytes(int $length); // Raw bytes | ||
+ | public function getString(int $length, int $bits = 6); // String [0-9a-zA-Z, | ||
+ | public function seed($seed = NULL); // No use with CS RNG, return TRUE always. | ||
+ | public function getState(); // Return string representation PRNG state. No use with CS RNG, return NULL. | ||
+ | public function setState(string $state); // Set PRNG state. No use with CS RNG, return TRUE always. | ||
+ | public function getCount(); // No use with CS RNG, return 0 always. | ||
+ | public function getReseedCycle(); | ||
+ | public function setReseedCycle(int $count); // No use with CS RNG, return TRUE always. | ||
+ | } | ||
+ | |||
+ | class RandamCS implements RandomIterface { | ||
+ | // random_*() functions OO API | ||
+ | // Description omitted, see RandomMT | ||
+ | } | ||
+ | |||
+ | // Implement True RNG which may block process when TRNG abstraction function is implemented | ||
+ | class RandamTRNG implements RandomIterface { | ||
+ | // Description omitted, see RandomMT | ||
+ | } | ||
+ | |||
+ | class RandomMT implements RandomInterface | ||
private int $count = 0; // Number of this state is used to generate random value | private int $count = 0; // Number of this state is used to generate random value | ||
private int $reseed = 100; // Max number of count to reseed automatically | private int $reseed = 100; // Max number of count to reseed automatically | ||
private string $state; // Binary PRNG state | private string $state; // Binary PRNG state | ||
| | ||
- | public function | + | public function |
- | return | + | $this->seed($seed); |
} | } | ||
| | ||
- | public function | + | public function |
- | | + | |
- | | + | if ($min && |
- | | + | return |
} | } | ||
+ | if ($min && $min > 0) { | ||
+ | // Return array of random values | ||
+ | while ($min--) { | ||
+ | $ret[] = mt_rand(); | ||
+ | } | ||
+ | return $ret; | ||
+ | } | ||
+ | trigger_error(' | ||
+ | return FALSE; | ||
+ | } | ||
+ | | ||
+ | public function getBytes(int $length) { | ||
+ | // Return raw random bytes | ||
+ | } | ||
+ | | ||
+ | public function getString(int $length, int $bits) { | ||
+ | // Return random string as in bin_to_readable() in ext/ | ||
+ | // Only 4 to 6 bits out of a byte is used to avoid disclosing raw PRNG state and simplicity. | ||
+ | } | ||
+ | | ||
+ | public function seed($seed = NULL) { | ||
+ | // This method code is pseudo code. New mt_srand() will return new state object for user. | ||
+ | // C written code updates $this-> | ||
+ | if ($seed) { | ||
+ | // Update state by user seed | ||
+ | mt_srand($seed); | ||
+ | } else { | ||
+ | // Seed by system generated random value | ||
+ | mt_srand(random_bytes(2500)); | ||
+ | } | ||
+ | return TRUE; | ||
+ | } | ||
+ | | ||
+ | public function getCount() { | ||
+ | return $this-> | ||
+ | } | ||
+ | | ||
+ | // Set/Get reseed cycle | ||
+ | public function getReseedCycle() { | ||
return $this-> | return $this-> | ||
+ | } | ||
+ | |||
+ | // Set reseed cycle | ||
+ | public function setReseedCycle(int $count) { | ||
+ | if (!is_int($count)) { | ||
+ | return FALSE; | ||
+ | } | ||
+ | $this-> | ||
+ | return TRUE; | ||
} | } | ||
} | } | ||
+ | </ | ||
+ | |||
+ | Random object has getBytes() and getString(). Implement function also. | ||
+ | |||
+ | <code php> | ||
+ | string mt_rand_bytes(int $length [, RandomMT $rand]) | ||
+ | string mt_rand_string(int $length [, RandomMT $rand]) | ||
+ | string rand_bytes(int $length [, Random $rand] ) // Alias of mt_rand_raw() now, but signature differs from MT rand to allow better PRNG in the future. | ||
+ | string rand_string(int $length [,int $bits [, Random $rand]]) // Alias of mt_rand_string() | ||
+ | string random_string(int $length [,int $bits]) | ||
</ | </ | ||
Line 115: | Line 214: | ||
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
- | Basically, none. | + | Basically, none if user wants random values. |
mt_srand()/ | mt_srand()/ | ||
+ | |||
+ | If users want static random values, they have to use RandomStatus object to get it. Use of mt_srand()/ | ||
===== Proposed PHP Version(s) ===== | ===== Proposed PHP Version(s) ===== | ||
Line 139: | Line 239: | ||
New | New | ||
- | * mt_rand_reseed = 10 for compiled/ | + | * mt_rand_reseed = 100 for compiled/ |
Line 159: | Line 259: | ||
===== Future Scope ===== | ===== Future Scope ===== | ||
- | Add object based predictable PRNG API. | + | Add Random objects as it required |
===== Proposed Voting Choices ===== | ===== Proposed Voting Choices ===== |
rfc/improve_predictable_prng_random.txt · Last modified: 2018/03/01 23:13 by carusogabriel