In this challenge we have a stream cipher based on LFSR and nonlinear filtering function. It has 128-bit LFSR secret state and we are also given 1600 keystream bits. Our goal is simply to recover the key which is the initial state. Here is the nonlinear filtering function:

f(v) = v[0] ^ v[1] ^ v[2] ^ v[31] ^ v[1]&v[2]&v[3]&v[64]&v[123] ^ v[25]&v[31]&v[32]&v[126] |

We can see that the two nonlinear terms are products of 4 and 5 variables. With high probability these terms are equal to zero and the filtering function becomes linear. More precisely, define

L(v) = v[0] ^ v[1] ^ v[2] ^ v[31] |

Then the probability $p$ that $f(v) = L(v)$ equals to $15/16 \times 31/32 + 1/16 \times 1/32 = 233/256$. Moreover, for 128 keystream bits the approximation can be expected to hold with probability $p^{128} \approx 2^{-17.384}$ or roughly $1/171000$. That is, if we sample 128 keystream bits roughly 171000 times we can expect that once they all are filtered using the linear function $L$. Then we can solve the (noiseless) linear system and recover the key. We can sample bits from the 1600-bit keystream since we expect that roughly $233/256\times 1600$ of them are filtered using the linear function and we will succeed once we choose 128 bits out of them. We just need to know the linear function that maps the original key to each of output keystream bits (i.e. repeated LFSR step and linear filtering). This can be done simply by running Snurre with linear filtering function on keys with single bit set (i.e. basis vectors) and putting the resulting streams into columns of a matrix.

The solution may take some time, e.g. around 1 hour on a common laptop. But it can be easily parallelized simply by running multiple instances.

The problem of solving noisy linear equations is called Learning Parity with Noise (LPN). There are various methods for approaching it. A good recent paper on this topic is “LPN Decoded” by Esser et al. For example, the described above method is called Pooled Gauss in the paper.