Skip to content

Linear Congruential Generator

Linear Congruent Generator (LCG)

  • Using about 6 sequential outputs you can generate all of the parameters and sync the state

Implementation

import math, functools

def findmodulus(outputs):
	temp = []
	for idx in range(0, len(outputs)-1):
		temp.append(outputs[idx+1] - outputs[idx])

	temp2 = []
	for idx in range(0, len(temp)-2):
		temp2.append(abs((temp[idx+2] * temp[idx]) - temp[idx+1]**2))

	return functools.reduce(math.gcd, temp2)

def findmult(x0, x1, x2, mod):
	temp  = x1 - x2 
	temp2 = pow(x0 - x1, -1, mod)
	return (temp * temp2) % mod

def findinc(x0, x1, a, mod):
	# x1 = x0*a + b
	# x1 - (x0*a) = b
	return (x1 - (x0 * a)) % mod

def findperoid(lcg):
	first = lcg.next()
	counter = 0

	while first != lcg.next():
		counter +=1
		if counter % 0xFFFFFF == 0:
			print(counter)

	print(f"Found Period: {counter}")

class LCG(object):
	"""docstring for LCG"""
	def __init__(self, seed=1337, a=1103515245, b=12345, c=0x7FFFFFFF):
		super(LCG, self).__init__()
		self.state = seed
		self.a = a
		self.b = b
		self.c = c

	def next(self):
		# seed = (seed * A + B) % C
		self.state = (self.state * self.a + self.b) % self.c
		return self.state

	def int_32(self, number):
		return int(0xFFFFFFFF & number)




if __name__ == '__main__':
	lcg = LCG()

	#### Computing the Paramaters
	seeds = []
	for _ in range(10):
		seeds.append(lcg.next())

	#Recover Mod
	found_mod = findmodulus(seeds)
	print(f"Mod: {found_mod}")


	#Recover Mult a
	found_a = findmult(seeds[0], seeds[1], seeds[2], found_mod)
	print(f"A: {found_a}")
		
	#Recover add b
	found_b = findinc(seeds[0], seeds[1], found_a, found_mod)
	print(f"B: {found_b}")

	assert found_mod == lcg.c
	assert found_a == lcg.a
	assert found_b == lcg.b

Attacks

Predicting values from a Linear Congruential Generator
Cracking a linear congruential generator