pseudo-key¶
This crypto challenge is all about reversing the encryption. The problem provided us with the encryption method, since each char in the ciphertext and plaintext is encrypted independantly, and does not change according to other characters in the string, i like to run all possible readable strings on the cipher text. This way, we could check our output and see if it gives us a readable answer. I'll say this is NOT the best way of solving this challenge, but it saves some time on reversing the encryption.
Understanding the Code¶
The million dollar question here is to understand the core code.
def encrypt(ptxt, key):
ptxt = ptxt.lower()
key = ''.join(key[i % len(key)] for i in range(len(ptxt))).lower()
ctxt = ''
for i in range(len(ptxt)):
if ptxt[i] == '_':
ctxt += '_'
continue
x = chr_to_num[ptxt[i]]
y = chr_to_num[key[i]]
ctxt += num_to_chr[(x + y) % 26]
return ctxt
i
will get converted into a number then the cipher text is just the sum of them mod 26 back to a char.By using my method of guessing all the posible chars, I don't really need to understand and reverse the algorithem since the programe does the work.
Solution¶
from string import ascii_lowercase
import itertools
from collections import defaultdict
chr_to_num = {c: i for i, c in enumerate(ascii_lowercase)}
num_to_chr = {i: c for i, c in enumerate(ascii_lowercase)}
def encrypt(ptxt, key):
ptxt = ptxt.lower()
key = ''.join(key[i % len(key)] for i in range(len(ptxt))).lower()
ctxt = ''
for i in range(len(ptxt)):
if ptxt[i] == '_':
ctxt += '_'
continue
x = chr_to_num[ptxt[i]]
y = chr_to_num[key[i]]
ctxt += num_to_chr[(x + y) % 26]
return ctxt
cipher="iigesssaemk"
key="iigesssaemk"
key = ''.join(key[i % len(key)] for i in range(len(cipher))).lower()
flag=''
posible=[]
for curr in range(0,len(key)):
posible.append([])
for y in ascii_lowercase:
x = chr_to_num[y]
z = chr_to_num[y]
if(num_to_chr[(x + z) % 26]==cipher[curr]):
flag+=y
if y not in posible[curr]:
posible[curr].append(y)
posible=list(itertools.product(*posible))
for x in range(0,len(posible)):
posible[x]=''.join(posible[x])
for choice in posible:
cipher="z_jjaoo_rljlhr_gauf_twv_shaqzb_ljtyut"
key=choice
key = ''.join(key[i % len(key)] for i in range(len(cipher))).lower()
flag=''
for curr in range(0,len(cipher)):
if(cipher[curr]=='_'):
flag+='_'
for y in ascii_lowercase:
x = chr_to_num[y]
z = chr_to_num[key[curr]]
if(num_to_chr[(x + z) % 26]==cipher[curr]):
flag+=y
print(flag)
Get the flag¶
To get the flag, we need a bit of searching and guessing. By looking at the output, we can summarize the flag to readable words.
Flag¶
flag{i_guess_pseudo_keys_are_pseudo_secure}