Подтвердить что ты не робот

Str_shuffle и randomness

А назад я написал случайный генератор строк, который строит строку с использованием символа mt_rand() th в строке до тех пор, пока не будет достигнута желаемая длина.

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() в одной строке. Мне очень нравится по этой простой причине, меньшее количество строк кода всегда хорошо.:)

Но когда я посмотрел str_shuffle в руководстве PHP, документация на нем была довольно легкой. Одна вещь, которую я действительно хотел узнать, это алгоритм, который он использует для случайности? В руководстве не упоминается, какая рандомизация выполняется для получения перетасованной строки. Если он использует rand() вместо mt_rand(), то, в конце концов, придерживаться моего текущего решения может быть лучше.

Итак, в основном я хотел бы знать, как str_shuffle рандомизирует строку. Используется ли rand() или mt_rand()? Я использую свою функцию случайных строк для генерации паролей, поэтому важно качество случайности.

UPDATE. Как уже указывалось, метод str_shuffle не эквивалентен уже используемому мне коду и будет менее случайным из-за того, что строковые символы остаются такими же, как и вход, только с изменением их порядка. Однако мне все еще интересно, как функция str_shuffle рандомизирует свою входную строку.

4b9b3361

Ответ 1

Лучшим решением будет mt_rand, который использует Mersenne Twister, который намного лучше.

Как уже отмечалось, метод 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);
}

Выходной тестRand()

enter image description here

Выход testShuffle()

enter image description here

Выходной тестMTRand()

enter image description here

Итак, в основном я хотел бы знать, как str_shuffle рандомизирует строку. Используется ли rand() или mt_rand()? Я использую свою случайную строчную функцию для генерации паролей, поэтому качество случайности имеет значение.

Вы можете ясно видеть, что str_shuffle производит почти такой же результат, как rand...

Ответ 2

Помните, что этот метод не следует использовать, если ваше приложение действительно сосредоточено на безопасности. Mersenne Twister НЕ криптографически защищен. PRNG может давать значения, которые статистически кажутся случайными, но их легко разбить.

Ответ 3

Все еще не криптографически безопасно, но вот способ использовать str_shuffle(), позволяя повторять символ, тем самым улучшая сложность...

generate_password($length = 8, $strength = 3) {
    if ($length < 6) $length = 6;
    if ($length > 32) $length = 32;
    // Excludes [0,O,o,1,I,i,L,l,1] on purpose for readability
    $chars = 'abcdefghjkmnpqrstuvwxyz';
    if ($strength >= 2) $chars .= '23456789';
    if ($strength >= 3) $chars .= strtoupper($lower);
    if ($strength >= 4) $chars .= '[email protected]#$%&?';
    return substr(str_shuffle(str_repeat($chars, $length)), 0, $length);
}

$chars повторяется $length раз до того, как строка перетасовывается, чтобы сделать это немного лучше, чем перетасовать только одно вхождение.

Мы используем это только в системах, которые не хранят конфиденциальную информацию;)