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.

Regards,

--
Yasuo Ohgaki
yohg...@ohgaki.net

Reply via email to