PHPのmt_rand関数のtwistマクロに一文字タイポがあり、修正されたのですが
http://git.php.net/?p=php-src.git;a=commitdiff;h=a0724d30817600540946b41e40f4cfc2a0c30f80
でリバートされてしまいました。
リバートのパッチはコレです。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 | index bc32f24..2dd05e7 100644 (file) --- a/ext/standard/rand.c +++ b/ext/standard/rand.c @@ -146,7 +146,7 @@ PHPAPI zend_long php_rand(void) #define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */ #define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */ -#define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((php_uint32)(-(php_int32)(loBit(v))) & 0x9908b0dfU)) +#define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((php_uint32)(-(php_int32)(loBit(u))) & 0x9908b0dfU)) /* {{{ php_mt_initialize */ |
修正しなくても実用的には問題がない、との判断もあったようです。そこでENTというエントロピーを分析するツールで簡単に確認してみました。
修正済の場合
0 1 2 3 4 5 6 7 8 9 10 11 12 | Entropy = 7.954269 bits per byte. Optimum compression would reduce the size of this 4000000 byte file by 0 percent. Chi square distribution for 4000000 samples is 250901.85, and randomly would exceed this value less than 0.01 percent of the times. Arithmetic mean value of data bytes is 111.4725 (127.5 = random). Monte Carlo value for Pi is 3.486975487 (error 10.99 percent). Serial correlation coefficient is -0.049294 (totally uncorrelated = 0.0). |
未修正の場合
0 1 2 3 4 5 6 7 8 9 10 11 12 | Entropy = 7.954382 bits per byte. Optimum compression would reduce the size of this 4000000 byte file by 0 percent. Chi square distribution for 4000000 samples is 250280.94, and randomly would exceed this value less than 0.01 percent of the times. Arithmetic mean value of data bytes is 111.5000 (127.5 = random). Monte Carlo value for Pi is 3.483663484 (error 10.89 percent). Serial correlation coefficient is -0.049192 (totally uncorrelated = 0.0). |
恐らく普通の疑似乱数が必要な場合の用途では問題はないと思われます。しかしこのテスト結果をもって、これで万全!とは行かずMT randが持つ非常に長い周期性が保たれているか?などの確認も必要です。
暗号理論的に安全な乱数が必要な場合は、random_bytesかrandom_intを使用すべきです。(利用できない場合はopenssl_random_pseudo_bytesか/dev/urandomなどを利用する)
一応、修正すべきでは?と提案していますが、どうなるかは判りません。