Path: blob/master/attacks/lcg/parameter_recovery.py
2589 views
from math import gcd12from sage.all import GF3from sage.all import is_prime_power456def attack(y, m=None, a=None, c=None):7"""8Recovers the parameters from a linear congruential generator.9If no modulus is provided, attempts to recover the modulus from the outputs (may require many outputs).10If no multiplier is provided, attempts to recover the multiplier from the outputs (requires at least 3 outputs).11If no increment is provided, attempts to recover the increment from the outputs (requires at least 2 outputs).12:param y: the sequential output values obtained from the LCG13:param m: the modulus of the LCG (can be None)14:param a: the multiplier of the LCG (can be None)15:param c: the increment of the LCG (can be None)16:return: a tuple containing the modulus, multiplier, and the increment17"""18if m is None:19assert len(y) >= 4, "At least 4 outputs are required to recover the modulus"20for i in range(len(y) - 3):21d0 = y[i + 1] - y[i]22d1 = y[i + 2] - y[i + 1]23d2 = y[i + 3] - y[i + 2]24g = d2 * d0 - d1 * d125m = g if m is None else gcd(g, m)2627assert is_prime_power(m), "Modulus must be a prime power, try providing more outputs"2829gf = GF(m)30if a is None:31assert len(y) >= 3, "At least 3 outputs are required to recover the multiplier"32x0 = gf(y[0])33x1 = gf(y[1])34x2 = gf(y[2])35a = int((x2 - x1) / (x1 - x0))3637if c is None:38assert len(y) >= 2, "At least 2 outputs are required to recover the multiplier"39x0 = gf(y[0])40x1 = gf(y[1])41c = int(x1 - a * x0)4243return m, a, c444546