SKIP TO MAIN CONTENT

[ WRITEUP NODE / FIELD REPORTS ]

SOLVED CHALLENGES & FIELD ANALYSIS

SECURITY RESEARCH KNOWLEDGE TECHNIQUES
B3S/WRITEUPS/GASLIGHTCTF-2026-WHERE-THE-DREAMS-START-2
← BACK TO ARCHIVE
EVENT: gaslightCTF 2026CATEGORY: CryptographyPOINTS: 500 PTS

GaslightCTF 2026 - Where the dreams start 2

AUTHORED BY:@bealthguy8/15/2026

Writeup – Where the dreams start Part 2

Challenge Recap

We are given:

  • Description:

    Musicians transpose keys regularly. Cryptanalysts transpose columns regularly.
    Keylength: key of cipher in Where the dream starts 1
    Keyword: ascii_lowercase[:keylength]

  • Output:
    T aiglhTtn0-t-yf-4}hfgsaitFrss2hk--fteel sgC{4p3-330gl!o

From Part 1 we learned that the Caesar key was K = 3 (the plaintext said “shift of three”).
So here:

  • keylength = 3
  • keyword = ascii_lowercase[:3] = "abc"

This is a columnar transposition cipher with 3 columns and keyword abc.


Decryption Steps

1. Determine column lengths

The ciphertext length is 57 characters (including spaces).
Since 57 / 3 = 19 exactly, each of the 3 columns has 19 characters.

2. Split the ciphertext into 3 equal chunks

col0 = "T aiglhTtn0-t-yf-4}"
col1 = "hfgsaitFrss2hk--fte"
col2 = "el  sgC{4p3-330gl!o"

3. Read row‑wise across columns

Because the keyword is abc, the column order is 0 → 1 → 2 (alphabetical).
Decryption is simply taking the first character of each chunk, then the second, and so on.

Doing this gives:

The flag is gaslightCTF{tr4nsp0s3-2-th3-k3y-0f-g-fl4t!}eo

4. Remove padding

The final eo is padding to make the plaintext length a multiple of 3.
The actual message is:

The flag is gaslightCTF{tr4nsp0s3-2-th3-k3y-0f-g-fl4t!}

So the flag is:

gaslightCTF{tr4nsp0s3-2-th3-k3y-0f-g-fl4t!}

Solver Script

# solve_part2.py
cipher = class="hljs-string">"T aiglhTtn0-t-yf-4}hfgsaitFrss2hk--fteel  sgC{4p3-330gl!o"

# Key length = 3 from part1
n = 3
col_len = len(cipher) // n

# Split into 3 columns
cols = [cipher[i*col_len:(i+1)*col_len] for i in range(n)]

# Read row-wise
plain = class="hljs-string">''.join(class="hljs-string">''.join(cols[j][i] for j in range(n)) for i in range(col_len))

# Remove padding if any (here class="hljs-string">'eo')
# But we can just extract the flag part
flag = plain.split(class="hljs-string">'gaslightCTF{')[1].split(class="hljs-string">'}')[0]
print(fclass="hljs-string">"gaslightCTF{{{flag}}}")

Output:

gaslightCTF{tr4nsp0s3-2-th3-k3y-0f-g-fl4t!}

Final Flag

gaslightCTF{tr4nsp0s3-2-th3-k3y-0f-g-fl4t!}