Challenge: All’s Fair in Love and CTFs · CTF: DalCTF 2026 · Category: Crypto · Difficulty: Easy

TL;DR

The challenge title is the whole hint. “All’s Fair”Playfair cipher. The image is the standard 5×5 Playfair key square (a Polybius grid with the even columns blanked out as a visual nudge), and the ciphertext decrypts to a cheeky little message about what we’d all do for a flag.

1
2
3
Ciphertext:  CLDYIKMHILSUKCLQBF
Plaintext:   ANYTHINGFORTHEFLAG
Flag:        dalctf{anything_for_the_flag}

The Challenge

We’re handed two artifacts:

  1. Ciphertext.txt — a single line of uppercase letters:

    1
    
    CLDYIKMHILSUKCLQBF
    
  2. Required_Challenge_Image.png — a grid of letters with some conspicuous gaps:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    ┌───┬───┬───┐
    │ A │ C │ E │
    ├───┼───┼───┤
    │ F │ H │ K │
    ├───┼───┼───┤
    │ L │ N │ P │
    ├───┼───┼───┤
    │ Q │ S │ U │
    ├───┼───┼───┤
    │ V │ X │   │
    └───┴───┴───┘
    

Plus the title — “All’s Fair in Love and CTFs” — which, in classic CTF tradition, is doing a lot of heavy lifting.


Step 1 — Read the Title Like a Crook

CTF authors love to hide the cipher name in plain sight. “All’s Fair” is a near-shameless pointer to the Playfair cipher, a digraph substitution cipher invented by Charles Wheatstone in 1854 (and popularized by Lord Playfair, hence the name). It encrypts pairs of letters using a 5×5 key square — exactly the kind of thing a grid-shaped image is begging us to use.

Two quick sanity checks that this is Playfair:

  • The ciphertext length is even. CLDYIKMHILSUKCLQBF is 18 characters — and Playfair always operates on an even number of letters (digraphs). ✅
  • No J. Playfair famously merges I and J into one cell. There’s no J in the ciphertext or in the grid. ✅

So far, so Playfair.


Step 2 — Reconstruct the Key Square

Here’s the fun part. The image looks like it only has three columns, but look at the letters:

1
2
3
4
5
A _ C _ E
F _ H _ K
L _ N _ P
Q _ S _ U
V _ X _ _

Those are the odd columns of the standard Polybius / Playfair square with the even columns erased. Fill the gaps back in and you get the textbook unkeyed square (with I/J sharing a cell):

1
2
3
4
5
A B C D E
F G H I K     ← I and J live here together
L M N O P
Q R S T U
V W X Y Z

In other words: no keyword at all — it’s just the plain alphabet (minus J) laid into the grid. The “missing columns” in the image are a stylistic flourish to make you recognize the Polybius layout rather than a separate puzzle.

Let’s assign coordinates (row, col), 0-indexed, which we’ll need for the decryption rules:

col0col1col2col3col4
row0ABCDE
row1FGHI/JK
row2LMNOP
row3QRSTU
row4VWXYZ

Step 3 — Playfair Decryption Rules

Playfair works on digraphs (letter pairs). To decrypt, you apply the inverse of the encryption rules:

  1. Same row → replace each letter with the one to its left (wrapping around).
  2. Same column → replace each letter with the one above it (wrapping around).
  3. Rectangle (different row and column) → replace each letter with the one in its own row but the other letter’s column (swap the column indices).

Split the ciphertext into pairs:

1
CL  DY  IK  MH  IL  SU  KC  LQ  BF

Now grind through them one at a time.

PairPositionsRuleResult
CLC(0,2) L(2,0)rectangle → swap columnsA(0,0) N(2,2) → AN
DYD(0,3) Y(4,3)same column → shift upY(4,3) T(3,3) → YT
IKI(1,3) K(1,4)same row → shift leftH(1,2) I(1,3) → HI
MHM(2,1) H(1,2)rectangle → swap columnsN(2,2) G(1,1) → NG
ILI(1,3) L(2,0)rectangle → swap columnsF(1,0) O(2,3) → FO
SUS(3,2) U(3,4)same row → shift leftR(3,1) T(3,3) → RT
KCK(1,4) C(0,2)rectangle → swap columnsH(1,2) E(0,4) → HE
LQL(2,0) Q(3,0)same column → shift upF(1,0) L(2,0) → FL
BFB(0,1) F(1,0)rectangle → swap columnsA(0,0) G(1,1) → AG

Reading the results straight across:

1
AN YT HI NG FO RT HE FL AG

Smush them together:

1
ANYTHINGFORTHEFLAG

ANYTHING FOR THE FLAG 🏴

Which, frankly, is the most honest sentence ever embedded in a crypto challenge.


Step 4 — Verify It Programmatically

Hand-decryption is error-prone, so here’s a tiny Python script that reproduces the whole thing:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
sq = ["ABCDE", "FGHIK", "LMNOP", "QRSTU", "VWXYZ"]   # I/J merged
pos = {ch: (r, c) for r, row in enumerate(sq) for c, ch in enumerate(row)}

ct = "CLDYIKMHILSUKCLQBF"
pt = ""
for i in range(0, len(ct), 2):
    a, b = ct[i], ct[i + 1]
    (ra, ca), (rb, cb) = pos[a], pos[b]
    if ra == rb:                                  # same row → shift left
        pt += sq[ra][(ca - 1) % 5] + sq[rb][(cb - 1) % 5]
    elif ca == cb:                                # same column → shift up
        pt += sq[(ra - 1) % 5][ca] + sq[(rb - 1) % 5][cb]
    else:                                         # rectangle → swap columns
        pt += sq[ra][cb] + sq[rb][ca]

print(pt)   # ANYTHINGFORTHEFLAG
1
2
$ python3 solve.py
ANYTHINGFORTHEFLAG

✅ Confirmed.


The Flag

The prompt told us to wrap the result in dalctf{}:

1
dalctf{anything_for_the_flag}

(Double-check casing/underscore conventions against the event rules — some scoreboards want dalctf{anythingfortheflag} or a different separator. The recovered plaintext is ANYTHINGFORTHEFLAG either way.)


Lessons Learned

  • The title is a hint. “All’s Fair” = Playfair. Authors plant the cipher name in the flavor text constantly — read it before you reach for the heavy machinery.
  • Even length + no J = think Playfair. Two cheap structural tells that narrow the search space instantly.
  • A grid image is usually a key square. When a crypto challenge ships a 5×5-ish grid, it’s almost always a Polybius/Playfair/ADFGVX-family square. Here the blanked columns were a recognition cue for the unkeyed standard square, not a second layer.
  • Verify by hand once, then script it. Hand-tracing teaches you the rules; the script proves you didn’t fat-finger a coordinate.

All’s fair in love and CTFs — and apparently we’ll do anything for the flag. 🚩