Crypto CTF — Learning permutation
Hello Everyone!
I will walk through a simple permutation/transposition CTF challenge in this write-up.
def check_password(pass_str):
length = len(pass_str)
if length != 15:
return False
part1 = "Spr3ue45"
for i in range(0, 15, 2):
if pass_str[i] != part1[i // 2]:
return False
part2 = "5PrcS3u"
for i in range(13, 0, -2):
if pass_str[i] != part2[(length - 2 - i) // 2]:
return False
return True
def main():
password = input("Enter password: ")
if check_password(password):
print(f"Welcome admin!\nFlag: SKR{{{password}}}")
else:
print("Login failed!")
if __name__ == "__main__":
main()
A little about permutation Cipher
Permutation cipher aka Transposition cipher is a cryptographic algorithm that swaps the position of a string (the secret message). It has three types, but we will solve the straight algorithm.
It takes the key (permutation position) and the string (secret message) to encrypt and encrypted string for decrypting.
This image shows how a simple permutation looks. Think of the “b” as the message block (character) and the numbers as the “index number” (position).
Solving the Challenge
We have two functions check_password
and main
looking at the main
function seems to be taking an input and storing it in a password variable. Then it passes the value to the check_password
function and if the return value is true it prints the “Welcome” message. And if it returns false it prints “Login failed!”.
def main():
password = input("Enter password: ")
if check_password(password):
print(f"Welcome admin!\nFlag: SKR{{{password}}}")
else:
print("Login failed!")
Now let’s look at the check_password
function.
length = len(pass_str)
if length != 15:
return False
First, it checks the length of the input password. If it’s not 15 the function returns false immediately. So, we know that the password length is 15.
part1 = "Spr3ue45"
for i in range(0, 15, 2):
# 0 2 4 6 8 10 12 14
if pass_str[i] != part1[i // 2]:
return False
Then there’s the first for
loop with the string part1
variable. It’s going to a for
loop from 0 -> 15, with a 2 increment. Then it matches the pass_str[i]
input password with the position from the for
loop part1[i // 2]
that takes the string from part1
divides with 2 to cancel the 2 increment. And if it doesn't match return false and exit the function.
Let’s see what I mean by canceling the 2 increments.
>>> for i in range(0,15,2):
... print(i)
...
0
2
4
6
8
10
12
14
>>> for i in range(0,15,2):
... print(i//2)
...
0
1
2
3
4
5
6
7
>>>
Now to the part2
second for
loop.
part2 = "5PrcS3u"
for i in range(13, 0, -2):
# 13 11 9 7 5 3 1
if pass_str[i] != part2[(length - 2 - i) // 2]:
return False
Just like the first for
loop it also uses a range from 13 -> 0 with (-2) increment. So this is matching the string from backward.
Print out the for
loop i
and (15 — 2 -i) // 2
to see the index.
Now let’s see how to solve it. First, we will have to extract the index position that’s matching with our password string. Which is 0 2 4 6 8 10 12 14 13 11 9 7 5 3 1
combined with the two for
loops.
Now all we have to do is rearrange the part1
and part2
string with the index number we got. Just like this
# 0 2 4 6 8 10 12 14 13 11 9 7 5 3 1
# S p r 3 u e 4 5 5 P r c S 3 u
# Sup3rS3cureP455
Now coding this in Python.
def pbox_cipher(code, key):
if len(code) != len(key):
raise ValueError("Code and key lengths must be the same")
cipher_text = [None] * len(code)
print(cipher_text)
for i, new_position in enumerate(key):
cipher_text[new_position] = code[i]
print(cipher_text)
return ''.join(cipher_text)
code = "Spr3ue455PrcS3u"
key = [0, 2, 4, 6, 8, 10, 12, 14, 13, 11, 9, 7, 5, 3, 1]
ciphered_text = pbox_cipher(code, key)
print("Original Code:", code)
print("Ciphered Text:", ciphered_text)
It only requires the cipher text and the key (index position).
The script first checks if the cipher length and the key length are the same or not. Because in the straight permutation cipher, the key and cipher length have to be the same. Then it creates a none
value array with the cipher length.
Later in the for
loop, we are just replacing the list with characters from cipher text following the key (index number).
More walkthroughs like this will be coming up next. If it was helpful please give a like (clap).
I also write in substack (in-depth, and hands-on), you can get it here https://cyberxcyber.substack.com/.
Thanks!
Twitter @_Golam Rabbany