-
Notifications
You must be signed in to change notification settings - Fork 0
nickm980/lcg-predictor
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Java's Random class uses a linear congruential generator which are pseudo-random and can be predicted because they are not truly random. The algorithm uses previous values to predict next pseudo-random numbers and is generated using the formula Xn+1 = (aXn+c) mod m with a, c, and m constant. The modulus keeps the next random number within bounds and the multiplier and addend generate the next number from the sequence. Internally Random uses nextseed = (oldseed * multiplier + addend) & mask where the bitwise & operator is equivalent to performing modulus 2^48 because both keep only the lower 48 bits. Basic usage of Random to generate a random number Random random = new Random(); random.nextInt(); The method below is the modified nextInt method from Random.java (https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/Random.java#L432) protected int nextInt(long oldseed) { long nextseed = (oldseed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1); return (int)(nextseed >>> 16); } As you probably noticed with the bitwise shift, the last 16 bits are discarded to create values that more closely resemble random numbers. To predict the original seed a possible solution is a brute force loop through all the possible last 2^16 bits until we find the combination of numbers that matches from two consecutive seeds (nextInt results). long result = 0; for (int i = 0; i < (1 << 16); i++) { long nextseed = ((long) oldseed << 16) + i; if (next(seed) == nextseed) { res = nextseed; break; } } Now the result can be passed into Random to predict the same future values as the original Random. There's one trick for getting the seed to work because when initializing a new instance of Random the seed is XOR with the multiplier. However this can be reversed by supplying a seed that is already XOR with the multiplier. Random Initializer public Random(long seed) { this.seed = (seed ^ multiplier) & mask; } So you would pass in your predicted seed like this new Random(seed^multiplier);
About
Java Linear Congruental Generator seed finder
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published