90 lines
2.1 KiB
Python
Executable File
90 lines
2.1 KiB
Python
Executable File
#!python3
|
|
import re
|
|
import string
|
|
|
|
with open("cypher", "r") as f:
|
|
cypher = f.read().strip()
|
|
assert len(cypher)%2==0
|
|
|
|
LOWERCASE_OFFSET = ord("a")
|
|
ALPHABET = string.ascii_lowercase[:16]
|
|
FLAG_ALPHABET = "0123456789abcdef"
|
|
FLAG_ALPHABET_B16 = []
|
|
a = ord('a')
|
|
|
|
def b16_encode(plain):
|
|
enc = ""
|
|
for c in plain:
|
|
binary = "{0:08b}".format(ord(c))
|
|
enc += ALPHABET[int(binary[:4], 2)]
|
|
enc += ALPHABET[int(binary[4:], 2)]
|
|
return enc
|
|
|
|
def b16_decode(encoded):
|
|
dec = ""
|
|
assert len(encoded)%2 == 0
|
|
for i in range(len(encoded)//2):
|
|
e1 = ALPHABET.index(encoded[2*i])
|
|
e2 = ALPHABET.index(encoded[2*i+1])
|
|
dec += chr((e1<<4) + e2)
|
|
return dec
|
|
|
|
for c in FLAG_ALPHABET:
|
|
FLAG_ALPHABET_B16.append(b16_encode(c))
|
|
|
|
KEY_SETS = []
|
|
for i in range(len(cypher)//2):
|
|
KEY_SET_0 = set()
|
|
KEY_SET_1 = set()
|
|
char_0 = ALPHABET.index(cypher[i*2])
|
|
char_1 = ALPHABET.index(cypher[i*2+1])
|
|
for flag_char in FLAG_ALPHABET_B16:
|
|
f0 = ord(flag_char[0]) - a
|
|
f1 = ord(flag_char[1]) - a
|
|
k0 = chr((char_0 - f0)%len(ALPHABET)+a)
|
|
k1 = chr((char_1 - f1)%len(ALPHABET)+a)
|
|
KEY_SET_0.add(k0)
|
|
KEY_SET_1.add(k1)
|
|
KEY_SETS.append(KEY_SET_0)
|
|
KEY_SETS.append(KEY_SET_1)
|
|
|
|
possible_kls = []
|
|
for kl in range(2, 16):
|
|
length_doable = True
|
|
key_options = [[]]*kl
|
|
for i in range(kl):
|
|
possible_cs = []
|
|
for c in KEY_SETS[i]:
|
|
c_possible = True
|
|
for j in range(i, len(KEY_SETS), kl):
|
|
if c not in KEY_SETS[j]:
|
|
c_possible = False
|
|
break
|
|
if c_possible:
|
|
possible_cs.append(c)
|
|
if len(possible_cs) == 0:
|
|
length_doable = False
|
|
break
|
|
else:
|
|
key_options[i] = possible_cs
|
|
if length_doable:
|
|
possible_kls.append(key_options)
|
|
print(len(possible_kls))
|
|
key = ""
|
|
for kl in possible_kls:
|
|
print(kl)
|
|
for kc in kl:
|
|
key += kc[0]
|
|
print(key)
|
|
|
|
b16_flag = ""
|
|
for i, c in enumerate(cypher):
|
|
c = ALPHABET.index(c)
|
|
k = ord(key[i%len(key)])-a
|
|
b16_flag += chr((c - k)%len(ALPHABET)+a)
|
|
print(b16_flag)
|
|
|
|
flag = b16_decode(b16_flag)
|
|
print(flag)
|
|
|