Skip to main content

HackTheBox Challenge sekur julius (Crypto)

410 words
Edwin | Shiro
Author
Edwin | Shiro
「 ✦ OwO ✦ 」
Table of Contents

Challenge Synopsis
#

Hidden deep in the forest was an ancient scroll, rumored to grant immense power to anyone who could read its shifting symbols. On Halloween, a curious traveler found the scroll, its letters strangely out of order. As they deciphered the message, the words slowly rearranged themselves, revealing a dark spell. But with the final shift, the traveler felt a cold presence behind them, whispering, “You were never meant to understand.” The forest grew silent, but the spell was already cast. (Source)

Solution
#

❯ cat source.py
from random import choices
import os

def julius_encrypt(msg, shift):
    ct = ''
    for p in msg:
        if p == ' ':
            ct += '0'
        elif not ord('A') <= ord(p) <= ord('Z'):
            ct += p
        else:
            o = ord(p) - 65
            ct += chr(65 + (o + shift) % 26)
    return ct

def encrypt(msg, key):
    for shift in key:
        msg = julius_encrypt(msg, shift)
    return msg

msg = open('secret.txt').read().upper()
secure_key = os.urandom(1337)

with open('output.txt', 'w') as f:
    f.write(encrypt(msg, secure_key))
    
❯ cat output.txt
JRYPBZR0GB0UNPXGUROBB0GJBGUBHFNAQGJRAGLSBHE!0GUVF0VF0N0CEBBS0BS0PBAPRCG0GB0CEBIR0LBH0GUNG0GUR0PNRFNE0PVCURE0VF0VAFRPHER0AB0ZNGGRE0UBJ0ZNAL0GVZRF0LBH0NCCYL0VG.0GUR0FRPHEVGL0BS0N0GUBHFNAQ0QVFGVAPG0FUVSGF0VF0RIRAGHNYYL0GUR0FNZR0NF0GUNG0BS0N0FVATYR0FUVSG.0RABHTU0ZHZOYVAT,0GNXR0LBHE0SYNT0NAQ0RAWBL0GUR0ERFG0BS0GUR0PBAGRFG.0ZNXR0FHER0LBH0JENC0GUR0SBYYBJVAT0GRKG0JVGU0GUR0UGO0SYNT0SBEZNG0GURRSSRPGVIRXRLFCNPRBSPNRFNEQRCRAQFBAGURFVMRBSGURNYCUNORG.

Even though the secure_key is long and randomly generated (which should make decryption hard), repeated Caesar shifts eventually reduce to a single effective Caesar shift. This is because the Caesar cipher is modular and commutative:

$$ ((A + s_1) + s_2 + ... + s_n) \mod 26 = (A + S) \mod 26 $$

So ultimately, the whole encryption just becomes one Caesar shift by the sum of all the shifts modulo 26.

❯ cat solve.py
#!/usr/bin/python3
def julius_decrypt(ct, shift):
    pt = ''
    for c in ct:
        if c == '0':
            pt += ' '  # Replace '0' back to space
        elif not ord('A') <= ord(c) <= ord('Z'):
            pt += c  # Non-alphabetic characters remain unchanged
        else:
            o = ord(c) - 65
            pt += chr(65 + (o - shift) % 26)
    return pt

def decrypt():
    enc = open('output.txt').read()
    for i in range(1, 26):  # Iterate over all possible shift values
        print(f'{i = } | {julius_decrypt(enc, i)}')

if __name__ == "__main__":
    decrypt()
    
❯ ./solve.py
...
i = 13 | WELCOME TO HACKTHEBOO TWOTHOUSANDTWENTYFOUR! THIS IS A PROOF OF CONCEPT TO PROVE YOU THAT THE CAESAR CIPHER IS INSECURE NO MATTER HOW MANY TIMES YOU APPLY IT. THE SECURITY OF A THOUSAND DISTINCT SHIFTS IS EVENTUALLY THE SAME AS THAT OF A SINGLE SHIFT. ENOUGH MUMBLING, TAKE YOUR FLAG AND ENJOY THE REST OF THE CONTEST. MAKE SURE YOU WRAP THE FOLLOWING TEXT WITH THE HTB FLAG FORMAT THEEFFECTIVEKEYSPACEOFCAESARDEPENDSONTHESIZEOFTHEALPHABET.
...

Flag: HTB{THEEFFECTIVEKEYSPACEOFCAESARDEPENDSONTHESIZEOFTHEALPHABET}