Description: The state of art on encryption, can you defeat it?
CjBPewYGc2gdD3RpMRNfdDcQX3UGGmhpBxZhYhFlfQA=
Cały kod szyfrujący jest tutaj.
Szyfrowanie jest bardzo proste, aż dziwne że zadanie było za 200 punktów. Szyfrowanie polega na podzieleniu wejściowego tekstu na 4 bajtowe kawałki (po dodaniu paddingu jeśli to konieczne, aby rozmiar wejścia był wielokrotnością 4 bajtów), rzutowanie ich na inta a następnie wykonywana jest operacja X xor X >>16
. Jeśli oznaczymy kolejnymi literami bajty tego inta uzyskujemy:
ABCD ^ ABCD >> 16 = ABCD ^ 00AB = (A^0)(B^0)(C^A)(D^B) = AB(C^A)(D^B)
Jak widać dwa pierwsze bajty są zachowywane bez zmian a dwa pozostałe bajty są xorowane z tymi dwoma niezmienionymi. Wiemy także że xor jest operacją odwracalną i (A^B)^B = A
możemy więc odwrócić szyfrowanie dwóch ostatnich bajtów xorując je jeszcze raz z pierwszym oraz drugim bajtem (pamiętając przy tym o kolejności bajtów)
data = "CjBPewYGc2gdD3RpMRNfdDcQX3UGGmhpBxZhYhFlfQA="
decoded = base64.b64decode(data)
blocks = struct.unpack("I" * (len(decoded) / 4), decoded)
output = ''
for block in blocks:
bytes = map(ord, struct.pack("I", block))
result = [bytes[0] ^ bytes[2], bytes[1] ^ bytes[3], bytes[2], bytes[3]]
output += "".join(map(chr, result))
print(output)
W wyniku czego uzyskujemy flagę: EKO{unshifting_the_unshiftable}
Cipher code is here.
The cipher is actually very simple, it was very strange that the task was worth 200 point. The cipher splits the input text in 4 byte blocks (after adding padding if necessary so that the input is a multiply of 4 bytes), casting each block to integer and the performing X xor X >>16
. If we mark each byte of the single block with consecutive alphabet letters we get:
ABCD ^ ABCD >> 16 = ABCD ^ 00AB = (A^0)(B^0)(C^A)(D^B) = AB(C^A)(D^B)
As can be noticed, first two bytes are unchanged and last two are xored with those two unchanged. We also know that xor is reversible and (A^B)^B = A
so we can revert the cipher of the last two bytes by xoring them again with first and second byte (keeping in mind the byte order).
data = "CjBPewYGc2gdD3RpMRNfdDcQX3UGGmhpBxZhYhFlfQA="
decoded = base64.b64decode(data)
blocks = struct.unpack("I" * (len(decoded) / 4), decoded)
output = ''
for block in blocks:
bytes = map(ord, struct.pack("I", block))
result = [bytes[0] ^ bytes[2], bytes[1] ^ bytes[3], bytes[2], bytes[3]]
output += "".join(map(chr, result))
print(output)
As a result we get: EKO{unshifting_the_unshiftable}