Tags: crypto
Rating:
## 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 = 0
for 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.