## PicoCTF 2021- New Caesar
:::info
:bulb: This is a writeup for the New Caesar challenge in PicoCTF.
:::
### :eight_spoked_asterisk: The Challenge
We found a brand new type of encryption, can you break the secret code? (Wrap with picoCTF{})<p>
lkmjkemjmkiekeijiiigljlhilihliikiliginliljimiklligljiflhiniiiniiihlhilimlhijil</p>
[new_caesar.py](https://mercury.picoctf.net/static/c9043977604318594ab73d126a01d0b1/new_caesar.py)
### :mag_right: Breakdown
Downloading and viewing the new_caesar.py file, we observe the following Python script
```python=
import string
LOWERCASE_OFFSET = ord("a")
ALPHABET = string.ascii_lowercase[:16]
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 shift(c, k):
t1 = ord(c) - LOWERCASE_OFFSET
t2 = ord(k) - LOWERCASE_OFFSET
return ALPHABET[(t1 + t2) % len(ALPHABET)]
flag = "redacted"
key = "redacted"
assert all([k in ALPHABET for k in key])
assert len(key) == 1
b16 = b16_encode(flag)
enc = ""
for i, c in enumerate(b16):
enc += shift(c, key[i % len(key)])
print(enc)
```
<p>
This Python code is a simple encryption program that performs a combination of Base16 encoding and a Caesar shift cipher on a given input string (`flag`). The key used for the Caesar shift is a single-character string (`key`).
</p>
<p>
The b16_encode function takes a string (`plain`) as input, converts each character to its 8-bit binary representation, and then encodes it using the first 4 bits and the next 4 bits separately, mapping them to characters in the defined `ALPHABET`. The result is a Base16 encoded string.
</p>
<p>
The shift function performs a Caesar shift on a character (`c`) using a key character (`k`). It calculates the shift based on the ASCII values of the characters and ensures that the result stays within the defined `ALPHABET`.
</p>
<p>
The following section sets the plaintext (`flag`) and the key (`key`), performing assertions to ensure that all characters in the key are in the defined `ALPHABET` and that the key is a single character. The Base16 encoded string (`b16`) is then encrypted using the Caesar shift with the key. The result (`enc`) is printed. The `enumerate` function is used to loop through the characters of the Base16 encoded string while keeping track of the index, and the key is repeated if its length is less than the length of the encoded string.
</p>
### :mag_right: Solution
<p>
Since we already have the encryption algorithm, we can reverse engineer a Python script to return the decrypted text- bruteforcing all 16 possible keys.
</p>
```python=
# import string
import string
# constants
LOWERCASE_OFFSET = ord("a")
ALPHABET = string.ascii_lowercase[:16]
# decode function
def b16_decode(cipher):
dec = ""
# loop through the cipher 2 characters at a time
for c in range(0, len(cipher), 2):
# turn the two characters into one binary string
b = ""
b += "{0:04b}".format(ALPHABET.index(cipher[c]))
b += "{0:04b}".format(ALPHABET.index(cipher[c + 1]))
# turn the binary string to a character and add
dec += chr(int(b, 2))
# return
return dec
# unshift the text
def unshift(c, k):
t1 = ord(c) - LOWERCASE_OFFSET
t2 = ord(k) - LOWERCASE_OFFSET
return ALPHABET[(t1 - t2) % len(ALPHABET)]
# encrypted flag
enc = "lkmjkemjmkiekeijiiigljlhilihliikiliginliljimiklligljiflhiniiiniiihlhilimlhijil"
# loop through all possible keys
for key in ALPHABET:
# initialize string
s = ""
# loop through the encrypted text
for i, c in enumerate(enc):
# unshift it based on key
s += unshift(c, key[i % len(key)])
# decode
s = b16_decode(s)
# print key
print(s)
```
### :triangular_flag_on_post: The Flag!!
Running the script above, we get 16 possible flags. However, only one seems plausible.
:::spoiler
picoCTF{et_tu?_431db62c5618cd75f1d0b83832b67b46}
:::