Edit suggested by fgrieu:
I have one hundred integers in $\{0,1,2,3,4,5\}$ which I suspect are consecutive values of $\lfloor x_n/2^{16}\rfloor\bmod6$ computed as $x_{n+1}:=a\cdot x_n+b\bmod m$, with $m=2^{31}$, and $(a,b)\in{(214013,2531011),(22695477,1)}$. How do I validate that hypothesis, find the $(a,b)$ used, and predict what follows in the sequence?
Question about "A competent implementation in a compiled language would take like a second on a modern desktop PC."
I wrote some code but they are expected to run 20 hours.
I am trying to find the random seed. First, I input my data in an array. Since I don't know my first data is what-th number generated by the server, I need to find it out. I only know the server shut down every thursday 2:00pm, and restart around 2:45-3:45pm the same day. When the server is on, ir generates 3 numbers every 45 seconds. The data I have is collected on fri 1:50 am, so my first data maybe the 2400-2640th number of the LCG.
I first run the rand 2399 times to discard the first 2399 numbers. Next, I loop 241 times to find my first data is what-th number generated by the server. (the uncertainity of the server restart time 2:45-3:45pm, 240 numbers per hour)
My method is: If 2400th x's bit 16 equal to bit 0 of $y_1$, then I check 2401th x's bit 16 and bit 0 of $y_2$, and so on. If there is unequal, break the loop then start another loop, compare 2401th x and bit 0 of $y_1$.
What is the better way to do it? I just started to learn c++ two weeks ago, please forgive my ignorance.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <iostream>
#include <inttypes.h>
using namespace std;
const int RESULT[3][7] = {
{0,1,0,1,1,1,1},
{1,0,1,0,0,0,0},
{0,1,1,0,1,0,0}
};
static unsigned long x;
int test_rand(void)
{
x = 214013 * x + 2531011; // or is it 22695477*x+1
return (int)((x >> 16) & 0x7FFF);
};
int onlyx16(void)
{
x = 214013 * x + 2531011; // or is it 22695477*x+1
return (x >> 16) & 1;
};
void chk_seed(unsigned long seed)
{
int d1[241]{};
int d2[241]{};
int d3[241]{};
x = seed;
for (int i = 0; i < 2399; i++) {
test_rand();
}
for (int i = 0; i < 241; i++)
{
d1[i] = onlyx16();
d2[i] = onlyx16();
d3[i] = onlyx16();
};
int correct = 0;
for (int k = 0; k < 236; k++)
{
correct = 0;
for (int i = 0; i < 7; i++)
{
if ((d1[i + k]) == RESULT[0][i])
{
correct += 1;
}
else {
correct = 0;
break;
};
if ((d2[i + k]) == RESULT[1][i])
{
correct += 1;
}
else {
correct = 0;
break;
};
if ((d3[i + k]) == RESULT[2][i])
{
correct += 1;
}
else {
correct = 0;
break;
};
};
if (correct == 21)
{
printf("seed 0x%d is OK\n", seed);
printf("results forecast:\n");
for (int round = 0; round < 5; round++)
{
printf("round%d ", round + 1);
int new_d[3]{};
for (int i = 0; i < 3; i++)
{
new_d[i] = test_rand()% 6;
printf("%d", new_d[i]);
};
printf("\n");
}
};
}
};
int main()
{
for (unsigned long seed = 0; seed < 0x100000000; seed++)
chk_seed(seed);
};
$x_{n+1} = (a \cdot x_{n} + b) \mod m$
In normal situation, $x_{n+1}$ and $x_n$ are known. But now I only know $x_n\mod 6$ and $x_{n+1}\mod 6$.
I have searched many website on google but I only find one question that talked about this problem.
Predicting values from a Linear Congruential Generator
However, it is not very clear and I still don't know what should I do after reading that. I hope someone can provide some math or example code, so that I can learn from trial and error.
I want to find a,b,m then use a C++ source code I found here to brute-force the seed.
I found an answer here that talked about how to find m, but I don't know $x_{n+1}$ and $x_n$.
https://security.stackexchange.com/questions/4268/cracking-a-linear-congruential-generator
I am new to this topic, but I desperately wanted to crack this PRNG, this PRNG made me suffered a lot, I decided to learn programming because of this PRNG. Thank you for your help!
rand
return $x_n$. They reportedly return bits 30..16 (that's 15 bits) of $x_n$, see this and this. Thus I doubt of «know $x_n\bmod6$». $\endgroup$