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.

Original writeup (https://nissen96.github.io/CTF-writeups/writeups/2021/pbctf/Alkaloid-Stream.html).