Time
Solved after the CTF with a lot of help from the admin (@asante).
Solution
In this challenge, we have a LFSR, a non-linear filter of algebraic degree 6, and its first 1001 outputs. Our goal is to recover its initial seed.
For LFSR clock and filter , the outputs are: Degree of these equations are too large, it is infeasible to solve directly. We need to lower the degree to solve , and here comes the idea of annihilators: annihilator of with is:
If we can find a function g with lower degree, we can solve for following system of equations instead:
We can find such function using sage:
from sage.crypto.boolean_function import BooleanFunction
B = BooleanPolynomialRing(6, ['x0', 'x64', 'x96', 'x128', 'x192', 'x255'])
x0, x64, x96, x128, x192, x255 = B.gens()
p = x0*x64*x96*x128*x192*x255 + ... + x128*x192*x255
f = BooleanFunction(p)
print(f.annihilator(f.algebraic_immunity()))
# output x0 + x1 + x2 + x3 + x4 + x5 + 1
# which means x0 + x64 + x96 + x128 + x192 + x255 + 1
Now we have a great linear annihilator.
For more about annihilator, algebraic immunity, and algebraic attack on LFSR, see this awesome slide.
To solve the system of equations, we can express the LFSR in matrix form, apply our annihilator on the matrix, and solve for , formally:
Solving for yields 4 solutions:
[+] Generated 293 equations
[+] Solution 0: ')A\x17U\xaf\x9d\x18\xbcn[\xed\x8aj\x00\xbc\xd4\xb39\xe1ef\xe7~/\xaa\xf2\xd7\x9e\x99\xdf\xc6j'
[+] Solution 1: 's\xf0Z\xea\x07\xa2\xc5H\xba\x1c*\xa5\x82_X\xf2\x1c\xfe\xd5\xb3\x11A%\xf0\x92\x0c\x8c\xbawa\x83w'
[+] Solution 2: '<\xdd,\xd8\xd3l\xa9\xa6\xe7s\xaap\xabn\xb4N\x9c\x95k\x97\x19\xc82\xb7\t\x92:P\xdd\xfad`'
[+] Solution 3: 'flag{StR34m_C1Ph3R_Annih1lat3D!}'