Description
Category: Crypto
Source: HackCON CTF 2019
Points: 198
Author: Jisoon Park(js00n.park)
Description:
I was told Vigenère Cipher is secure as long as length(key) == length(message). So I did just that!
Break this: g4iu{ocs_oaeiiamqqi_qk_moam!}e0gi
Write-up
Vigenère Cipher 문제이고, key와 plaintext의 길이가 같다고 한다.
이 경우, plaintext의 각 byte마다 서로 다른 key가 독립적으로 사용되기 때문에 key를 알아낼 수가 없다.
현 상태에서 알 수 있는 것은 flag format인 "d4rk{flag_text}c0de" 밖에 없으니, 일단 알 수 있는 부분이라도 key를 찾아보자.
import string
ct = "g4iu{ocs_oaeiiamqqi_qk_moam!}e0gi"
pt = "d4rk{aaaaaaaaaaaaaaaaaaaaaaa}c0de"
r = ""
for c, p in zip(ct, pt):
if c in string.lowercase:
c_idx = string.lowercase.find(c)
p_idx = string.lowercase.find(p)
r += string.lowercase[(c_idx - p_idx) % 26]
else:
r += c
print r
알려진 부분에 대한 key를 구해보았더니 flag format이 그대로 나왔다.
주어진 암호문이 flag를 flag로 암호화 한 것임을 유추해 볼 수 있다.
flag string 부분도 구해 보자.
Vigenère Cipher에서 임의의 문자 c를 c로 암호화 하게 되면 index가 두 배가 되어 2의 배수 번째에 있는 문자들만 암호문으로 나오게 된다.
26개의 영문자가 13개로 대응되게 되니, 암호문을 이루는 하나의 글자는 각각 두 개의 평문 문자 중의 하나로 복호화 될 수 있게 된다.
이 대응 관계를 dict로 만들어 보자.
d = dict()
for i in range(26):
k = string.lowercase[i * 2 % 26]
if k in d:
d[k] = d[k] + string.lowercase[i]
else:
d[k] = string.lowercase[i]
print d
이제 평문을 복호화 하기 위해서는 가능한 구성 중에 의미 있는 단어로 구성된 flag를 찾아내야 한다.
가능한 조합 중에서 영단어에 존재하는 단어들만 뽑아내보자. (코드)
찾아진 후보 단어들을 조합하여 아래와 같은 flag를 만들 수 있었다.
Flag : d4rk{how_uncreative_is_that!}c0de