$output = str_shuffle("12345");

E.g. $output is now 25134 How do I find out what numbers came out of mt_rand() to allow for the shuffle I want to know this because I want the seed of mt_rand() and str_shuffle() uses mt_rand() which is not cryptographically secure as it uses Mersenne Twister (Wikipedia) I know shuffle for python is using the Fisher Yates shuffle (Wikipedia) but I have no idea how it works in php. you can get the seed used if you have 624 outputs using mersenne-twister-recover (GitHub) or you can brute force the seed with untwister (GitHub)

  • So the question actually is "how can I know the seed of mt_rand() after I've called it for the 1st time"? – Xenos Jun 29 '18 at 15:10
  • No str_shuffle probably uses mt_rand() a couple times and its not going to be the only outputs from mt_rand() anyway that I use – OfficialNoob Jun 29 '18 at 15:13

According to PHP 7.2.7 sources, the str_shuffle function uses php_string_shuffle which does

while (--n_left) {
    rnd_idx = php_rand();
    RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
    if (rnd_idx != n_left) {
        temp = str[n_left];
        str[n_left] = str[rnd_idx];
        str[rnd_idx] = temp;

So I guess you would like to know the intermediate values of rnd_idx (since php_rand() is an alias of php_mt_rand()).

But RAND_RANGE is a macro defined as #define RAND_RANGE(__n, __min, __max, __tmax) (__n) = php_mt_rand_range((__min), (__max)) so the 1st value of the php_rand() is already instantly lost.

Hence, you won't get the list of all intermediate mt_range() values.

Still, knowing that the algorithm there seems to be at each round, swap the current letter with a random letter before in the input string; the 1st round takes the last letter as the current one; the next round takes the letter previous current letter as the new current letter then you can get the mt_rand value by reasoning backward.

If ABCD is the input value and BADC is the result, then it means the values were 2;2;0 (ABCD => ABDC => ABDC => BADC) but you still don't know the value of the "lost" calls to php_mt_rand. So the sequence of mt_rand was actually ?;2;?;2;?;0 which matches the seed 4 and 25: if you do mt_srand(4); echo str_shuffle('ABCD'); then you'll get BADC and same if your seed is set to 25. You would need a pretty long chain of unique characters to get a sequence long enough to match only one seed.

  • Could you edit it to add an example in python as thats the full question then its still useful as brute forcing the seed is still possible – OfficialNoob Jun 29 '18 at 16:26
  • It's not a programmer exchange website, such request would more fit stackoverflow. From a cryptographic point of view, the interesting thing is the concept and general process, not the implementation details. – Xenos Jun 29 '18 at 16:36
  • Okay I will edit my question – OfficialNoob Jun 29 '18 at 16:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.