str_shuffle和随机性

2022-08-31 00:25:41

不久前,我编写了一个随机字符串生成器,该生成器使用字符串中的第mt_rand()个字符构建字符串,直到达到所需的长度。

public function getPassword ()
{
    if ($this -> password == '')
    {
        $pw             = '';
        $charListEnd    = strlen (static::CHARLIST) - 1;
        for ($loops = mt_rand ($this -> min, $this -> max); $loops > 0; $loops--)
        {
            $pw .= substr (static::CHARLIST, mt_rand (0, $charListEnd), 1);
        }
        $this -> password   = $pw;
    }
    return $this -> password;
}

(CHARLIST 是一个类常量,其中包含密码的字符池。$min和$max是长度限制)

今天,在完全研究其他东西时,我偶然发现了以下代码:

function generateRandomString ($length = 10) {    
    return substr(str_shuffle ("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, $length);
}

这实现了与我在一行中循环mt_rand()代码几乎相同的效果。我真的很喜欢它,原因很简单,更少的代码行总是一件好事。:)

但是当我在PHP的手册中查找str_shuffle时,它的文档非常轻。我真正渴望学习的一件事是它使用什么算法来实现随机性?该手册没有提到进行哪种随机化以获得随机字符串。如果它使用rand()而不是mt_rand(),那么坚持我目前的解决方案可能更好。

所以基本上我想知道str_shuffle如何随机化字符串。它是使用rand()还是mt_rand()?我正在使用我的随机字符串函数来生成密码,因此随机性的质量很重要。

更新:如前所述,str_shuffle方法并不等同于我已经使用的代码,并且由于字符串的字符与输入保持相同,因此随机性会降低,只是它们的顺序发生了变化。但是,我仍然很好奇str_shuffle函数如何随机化其输入字符串。


答案 1

更好的解决方案是使用Mersenne Twister,这要好得多。mt_rand

如前所述,str_shuffle方法并不等同于我已经使用的代码,并且由于字符串的字符与输入保持相同,因此随机性会降低,只是它们的顺序发生了变化。但是,我仍然很好奇str_shuffle函数如何随机化其输入字符串。

要使输出相等,只需使用并查看每个函数的可视表示形式0,1

简单的测试代码

header("Content-type: image/png");
$im = imagecreatetruecolor(512, 512) or die("Cannot Initialize new GD image stream");
$white = imagecolorallocate($im, 255, 255, 255);
for($y = 0; $y < 512; $y ++) {
    for($x = 0; $x < 512; $x ++) {
        if (testMTRand()) { //change each function here 
            imagesetpixel($im, $x, $y, $white);
        }
    }
}
imagepng($im);
imagedestroy($im);

function testMTRand() {
    return mt_rand(0, 1);
}

function testRand() {
    return rand(0, 1);
}

function testShuffle() {
    return substr(str_shuffle("01"), 0, 1);
}

输出测试兰特()

enter image description here

输出测试随机()

enter image description here

输出测试MTRand()

enter image description here

所以基本上我想知道str_shuffle如何随机化字符串。它是使用rand()还是mt_rand()?我正在使用我的随机字符串函数来生成密码,因此随机性的质量很重要。

您可以清楚地看到,产生几乎与...str_shufflerand


答案 2

请注意,如果您的应用程序真正关注安全性,则不应使用此方法。Mersenne Twister在加密上并不安全。PRNG可以产生在统计上看起来是随机的,但仍然容易破坏的值。


推荐