Path: blob/master/attacks/lcg/truncated_state_recovery.py
2589 views
from sage.all import QQ1from sage.all import ZZ2from sage.all import matrix3from sage.all import vector456def attack(y, k, s, m, a, c):7"""8Recovers the states associated with the outputs from a truncated linear congruential generator.9More information: Frieze, A. et al., "Reconstructing Truncated Integer Variables Satisfying Linear Congruences"10:param y: the sequential output values obtained from the truncated LCG (the states truncated to s most significant bits)11:param k: the bit length of the states12:param s: the bit length of the outputs13:param m: the modulus of the LCG14:param a: the multiplier of the LCG15:param c: the increment of the LCG16:return: a list containing the states associated with the provided outputs17"""18diff_bit_length = k - s1920# Preparing for the lattice reduction.21delta = c % m22y = vector(ZZ, y)23for i in range(len(y)):24# Shift output value to the MSBs and remove the increment.25y[i] = (y[i] << diff_bit_length) - delta26delta = (a * delta + c) % m2728# This lattice only works for increment = 0.29B = matrix(ZZ, len(y), len(y))30B[0, 0] = m31for i in range(1, len(y)):32B[i, 0] = a ** i33B[i, i] = -13435B = B.LLL()3637# Finding the target value to solve the equation for the states.38b = B * y39for i in range(len(b)):40b[i] = round(QQ(b[i]) / m) * m - b[i]4142# Recovering the states43delta = c % m44x = list(B.solve_right(b))45for i, state in enumerate(x):46# Adding the MSBs and the increment back again.47x[i] = int(y[i] + state + delta)48delta = (a * delta + c) % m4950return x515253