Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jvdsn
GitHub Repository: jvdsn/crypto-attacks
Path: blob/master/attacks/lcg/parameter_recovery.py
2589 views
1
from math import gcd
2
3
from sage.all import GF
4
from sage.all import is_prime_power
5
6
7
def attack(y, m=None, a=None, c=None):
8
"""
9
Recovers the parameters from a linear congruential generator.
10
If no modulus is provided, attempts to recover the modulus from the outputs (may require many outputs).
11
If no multiplier is provided, attempts to recover the multiplier from the outputs (requires at least 3 outputs).
12
If no increment is provided, attempts to recover the increment from the outputs (requires at least 2 outputs).
13
:param y: the sequential output values obtained from the LCG
14
:param m: the modulus of the LCG (can be None)
15
:param a: the multiplier of the LCG (can be None)
16
:param c: the increment of the LCG (can be None)
17
:return: a tuple containing the modulus, multiplier, and the increment
18
"""
19
if m is None:
20
assert len(y) >= 4, "At least 4 outputs are required to recover the modulus"
21
for i in range(len(y) - 3):
22
d0 = y[i + 1] - y[i]
23
d1 = y[i + 2] - y[i + 1]
24
d2 = y[i + 3] - y[i + 2]
25
g = d2 * d0 - d1 * d1
26
m = g if m is None else gcd(g, m)
27
28
assert is_prime_power(m), "Modulus must be a prime power, try providing more outputs"
29
30
gf = GF(m)
31
if a is None:
32
assert len(y) >= 3, "At least 3 outputs are required to recover the multiplier"
33
x0 = gf(y[0])
34
x1 = gf(y[1])
35
x2 = gf(y[2])
36
a = int((x2 - x1) / (x1 - x0))
37
38
if c is None:
39
assert len(y) >= 2, "At least 2 outputs are required to recover the multiplier"
40
x0 = gf(y[0])
41
x1 = gf(y[1])
42
c = int(x1 - a * x0)
43
44
return m, a, c
45
46