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

Reply via email to