## Short description
For each input bit, a `key` number and `fake` number is generated. A random `keystream` is generated and a corresponding public list, such that```public[i] = [fake[i], key[i]] if keystream[i] else [key[i], fake[i]]```The input is XORed with the random `keystream` to generate the ciphertext and this is output together with `public`. But `fake` was generated by just XORing values from `key`, and based on this, we can guess which values from `public` are from `fake`. The others must be from `key`, allowing us to recover the `keystream` and decrypt the flag.
## Exploit script
The following script finds the values that must have come from `key`, one by one from last to first:
```key = []k = 0for i in range(ln):    for a, b in public:        if a == k:            key.append(b)            break        elif b == k:            key.append(a)            break    k = xor_list(key[-ln // 3:])```The `keystream` can then be recovered and the flag decrypted:```keystream = recover_keystream(key, public)flag = bits_to_bytes(xor(enc, keystream))print(flag.decode())```
Click the link for a much more detailed writeup.