Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jvdsn
GitHub Repository: jvdsn/crypto-attacks
Path: blob/master/attacks/lcg/truncated_state_recovery.py
2589 views
1
from sage.all import QQ
2
from sage.all import ZZ
3
from sage.all import matrix
4
from sage.all import vector
5
6
7
def attack(y, k, s, m, a, c):
8
"""
9
Recovers the states associated with the outputs from a truncated linear congruential generator.
10
More information: Frieze, A. et al., "Reconstructing Truncated Integer Variables Satisfying Linear Congruences"
11
:param y: the sequential output values obtained from the truncated LCG (the states truncated to s most significant bits)
12
:param k: the bit length of the states
13
:param s: the bit length of the outputs
14
:param m: the modulus of the LCG
15
:param a: the multiplier of the LCG
16
:param c: the increment of the LCG
17
:return: a list containing the states associated with the provided outputs
18
"""
19
diff_bit_length = k - s
20
21
# Preparing for the lattice reduction.
22
delta = c % m
23
y = vector(ZZ, y)
24
for i in range(len(y)):
25
# Shift output value to the MSBs and remove the increment.
26
y[i] = (y[i] << diff_bit_length) - delta
27
delta = (a * delta + c) % m
28
29
# This lattice only works for increment = 0.
30
B = matrix(ZZ, len(y), len(y))
31
B[0, 0] = m
32
for i in range(1, len(y)):
33
B[i, 0] = a ** i
34
B[i, i] = -1
35
36
B = B.LLL()
37
38
# Finding the target value to solve the equation for the states.
39
b = B * y
40
for i in range(len(b)):
41
b[i] = round(QQ(b[i]) / m) * m - b[i]
42
43
# Recovering the states
44
delta = c % m
45
x = list(B.solve_right(b))
46
for i, state in enumerate(x):
47
# Adding the MSBs and the increment back again.
48
x[i] = int(y[i] + state + delta)
49
delta = (a * delta + c) % m
50
51
return x
52
53