On 30.01.2017 at 13:32, Yasuo Ohgaki wrote: > Hi all, > > Following code is problematic and needs proper reseeding to work. > > // We need the same random numbers here > mt_srand(1234); > for ($i=0; $i < 10; $i++) { > $my_rand[] = mt_rand(); > } > > Somewhere later in code > > // We need somewhat random numbers for non CS purpose > for ($i=0; $i < 10; $i++) { > $my_other_rand[] = mt_rand(); > } > > $my_other_rand array is not random at all for the app. This applies to > rand()/srand() as well as all functions that use rand and rand/MT rand > internally. e.g. shuffle(). rand() is alias of mt_rand() in PHP 7.1, it can > cause serious problem. i.e. srand(1234) forces mt_rand() to generate non > random numbers. > > In addition, this behavior persists across requests because once > BG(mt_rand_is_seeded)/BG(rand_is_seeded) are set to 1, they are kept for > the process. Therefore, subsequent mt_rand()/rand(), including any > functions use rand/MT rand internally such as shuffle(), call in other > requests are not random. > > In order to get random numbers, we need to reseed RNG. > > Currently, it is possible to reseed like (int overflow is ignored) > > $seed = unpack("l", file_get_contents("/dev/urandom", false, NULL, 0, 4)); > mt_srand($seed[1]); > for ($i=0; $i < 10; $i++) { > $my_other_rand[] = mt_rand(); > } > > OR for PHP 7 > > mt_srand(random_int(PHP_INT_MIN, PHP_INT_MAX)); > for ($i=0; $i < 10; $i++) { > $my_other_rand[] = mt_rand(); > } > > Requiring these reseeding code for most mt_rand()/rand() calls is not > preferred behavior. > > Proposal: > 1) Add BG(mt_rand_is_user_seeded) and BG(rand_is_user_seeded). If they are > 1, set BG(mt_rand_is_seeded)=0 and BG(rand_is_seeded)=0. > 2) Make srand(0) and mt_srand(0) to force RNG reseeding by PHP. > > Outcome: > 1) resolves "across requests" non random numbers. > 2) simplifies reseeding. > > Problem: > 1) Added new BG values are BC for released versions. Simply reseeding by > current GENERATE_SEED() macro is weak and too easy to be guessed even with > MT rand. i.e. Setting BG(mt_rand_is_seeded)=0 and BG(rand_is_seeded)=0 at > RINIT is not exactly a good idea. (There is improvement discussion in > "Improving mt_rand() seed" thread) > 2) Manual reseeding API, srand(0)/mt_srand(0), is not compatible with older > versions. > > Open Issue: > 1) and 2), apply these to released versions or not. > > This idea is acceptable, but I don't like this idea myself. > > It seems we should do something for this, documentation for released > versions at least. > Any better ideas are appreciated.
Just a quick idea: <?php class PNRG { public function __construct($seed = null) {…} public function get() {…} } -- Christoph M. Becker -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php