Tags: crypto classic-crypto
Rating:
We're given an encrypted flag and the python code used to encrypt it.
```
import random
W = 7
perm = range(W)
random.shuffle(perm)
msg = open("flag.txt").read().strip()
while len(msg) % (2*W):
msg += "."
for i in xrange(100):
msg = msg[1:] + msg[:1]
msg = msg[0::2] + msg[1::2]
msg = msg[1:] + msg[:1]
res = ""
for j in xrange(0, len(msg), W):
for k in xrange(W):
res += msg[j:j+W][perm[k]]
msg = res
print msg
```
Basically the code selects a random permutation of $\\{1,2,...,7\\}$, puts some padding at the end of the string to get a length multiple of $14$ and then encrypts the string. The encryption procedure works as follows:
* Swaps the first and the last element of the string
* Puts the characters with even index in the first half of the string and the ones with odd index in the second part (e.g. `ABCDEFGH --> ACEGBDFH`)
* Swaps again the first and the last element
* Split the string in blocks of $7$ characters and apply the selected permutation to each one
* Iterate this process $100$ times
Because we are working on a string with length multiple of the length of the permutation and also even, we can see the entire process itself as a permutation, so it must have a sort of fixed point: iterating this process with the right permutation will produce our flag. Fortunately, we have only $7!=5040$ permutations to test, and looking for the word `FLAG` in the result gives what we needed:
```
import random
import itertools
msg2 = "L{NTP#AGLCSF.#OAR4A#STOL11__}PYCCTO1N#RS.S"
for perm in itertools.permutations(range(7)):
msg = msg2
for i in xrange(100):
msg = msg[1:] + msg[:1]
msg = msg[0::2] + msg[1::2]
msg = msg[1:] + msg[:1]
res = ""
for j in xrange(0, len(msg), 7):
for k in xrange(7):
res += msg[j:j+7][perm[k]]
msg = res
if "FLAG" in msg:
print(msg)
```
Flag: `FLAG{##CL4SS1CAL_CRYPTO_TRANSPOS1T1ON##}`