1. Home
  2. Cryptography & Network Security
  3. Playfair Cipher

Playfair Cipher

A 5×5 square built from a key word encrypts two letters at a time, using three simple rules for rows, columns and rectangles.

Interactive 3DBeginner11 min readCNSUpdated

Drag to rotate · Right-drag to pan · Click, then scroll to zoom · Space play · ←→ step

What's happening

Pseudocode

    Try this in the 3D model

    • Press Build square. What happens to the second A in MONARCHY?
    • Press Encrypt. Which pairs use the rectangle rule, and which use the row or column rule?
    • Press Try BALLOON. Where does the filler X go, and why?
    • After encrypting, press Decrypt. Is the result exactly the original message?

    Why encrypt two letters at a time?

    The Caesar cipher swaps one letter for another, so the letter counts of English survive and give the key away. Playfair encrypts pairs of letters (digraphs). There are 26 single letters but 600 different pairs, so the most common pair, TH, is far less obvious than the most common letter, E.

    Charles Wheatstone invented it in 1854 and his friend Lord Playfair promoted it, which is how it got the wrong name. The British army used it in the Boer War and the First World War because it was fast to do by hand and needed nothing but a pencil.

    Step 1: build the key square

    1. Write the letters of the key word into a 5 × 5 grid, row by row, skipping any letter that is already there.
    2. Fill the remaining cells with the rest of the alphabet, in order.
    3. 26 letters do not fit in 25 cells, so I and J share one cell.

    With the key MONARCHY:

    col 0 col 1 col 2 col 3 col 4
    row 0 M O N A R
    row 1 C H Y B D
    row 2 E F G I/J K
    row 3 L P Q S T
    row 4 U V W X Z

    Step 2: split the message into pairs

    • Write J as I and drop spaces and punctuation.
    • Split into pairs from the left.
    • If a pair would contain two equal letters, put an X between them. BALLOON becomes BA LX LO ON.
    • If one letter is left over at the end, give it an X partner. (If the letter itself is X, use Q instead.)

    Step 3: encrypt each pair

    Find both letters in the square. Exactly one of three rules applies:

    Where the two letters are Encrypt Decrypt
    Same row Take the letter to the right of each (wrap to the start of the row) Take the letter to the left
    Same column Take the letter below each (wrap to the top) Take the letter above
    Different row and column They are corners of a rectangle: each letter is replaced by the letter in its own row and the other letter’s column The same rule (it undoes itself)

    Worked example: INSTRUMENTS, key MONARCHY

    The pairs are IN ST RU ME NT SX (11 letters, so the last S gets an X partner).

    Pair Positions (row, column) Rule Result
    IN I (2, 3), N (0, 2) Rectangle GA
    ST S (3, 3), T (3, 4) Same row TL (T wraps around to L)
    RU R (0, 4), U (4, 0) Rectangle MZ
    ME M (0, 0), E (2, 0) Same column CL
    NT N (0, 2), T (3, 4) Rectangle RQ
    SX S (3, 3), X (4, 3) Same column XA (X wraps around to A)

    The ciphertext is GATLMZCLRQXA. Some textbooks pad with Z instead of X: then the last pair is SZ, a rectangle, which gives TX.

    Decryption

    The receiver builds the same square from the same key and reverses each move: left instead of right, up instead of down. The rectangle rule is its own inverse. Decrypting GATLMZCLRQXA gives INSTRUMENTSX, and the reader simply drops the filler X that makes no sense.

    How strong is it?

    Playfair was a real improvement over single-letter ciphers:

    • There are 25! ≈ 1.6 × 10²⁵ possible squares, so trying every key is hopeless.
    • A letter does not always encrypt to the same letter. In the example, the two Ts became L and Q.

    But it is still breakable by hand with enough text:

    • The same pair always encrypts to the same pair, so pair frequencies survive (TH, HE, IN, ER are the most common in English).
    • A pair and its reverse give reversed results: if AB → XY, then BA → YX.
    • A ciphertext never contains a doubled pair like EE, and a letter never encrypts to itself. Each of these facts narrows the search.

    Code

    def build_square(key: str) -> list[str]:
        square = []
        for ch in (key + "ABCDEFGHIKLMNOPQRSTUVWXYZ").upper().replace("J", "I"):
            if ch.isalpha() and ch not in square:
                square.append(ch)
        return square                               # 25 letters, row by row
    
    def pairs(text: str) -> list[str]:
        s = [ch for ch in text.upper().replace("J", "I") if ch.isalpha()]
        out, i = [], 0
        while i < len(s):
            a = s[i]
            b = s[i + 1] if i + 1 < len(s) else None
            if b is None or a == b:                 # doubled letter or odd end
                out.append(a + ("Q" if a == "X" else "X"))
                i += 1
            else:
                out.append(a + b)
                i += 2
        return out
    
    def playfair(text: str, key: str, decrypt: bool = False) -> str:
        sq = build_square(key)
        pos = {ch: divmod(i, 5) for i, ch in enumerate(sq)}
        d = -1 if decrypt else 1
        todo = [text[i:i + 2] for i in range(0, len(text), 2)] if decrypt else pairs(text)
        out = []
        for a, b in todo:
            (ra, ca), (rb, cb) = pos[a], pos[b]
            if ra == rb:                            # same row: right (left to decrypt)
                out += [sq[ra * 5 + (ca + d) % 5], sq[rb * 5 + (cb + d) % 5]]
            elif ca == cb:                          # same column: down (up to decrypt)
                out += [sq[(ra + d) % 5 * 5 + ca], sq[(rb + d) % 5 * 5 + cb]]
            else:                                   # rectangle: swap the columns
                out += [sq[ra * 5 + cb], sq[rb * 5 + ca]]
        return "".join(out)
    
    c = playfair("instruments", "monarchy")
    print(c)                                        # GATLMZCLRQXA
    print(playfair(c, "monarchy", decrypt=True))    # INSTRUMENTSX
    #include <cctype>
    #include <iostream>
    #include <string>
    using namespace std;
    
    struct Playfair {
        string sq;                                  // 25 letters, row by row
        int row[26] = {}, col[26] = {};
    
        explicit Playfair(const string& key) {
            for (char ch : key + "ABCDEFGHIKLMNOPQRSTUVWXYZ") {
                ch = toupper(static_cast<unsigned char>(ch));
                if (ch == 'J') ch = 'I';
                if (isalpha(static_cast<unsigned char>(ch)) && sq.find(ch) == string::npos) sq += ch;
            }
            for (int i = 0; i < 25; i++) { row[sq[i] - 'A'] = i / 5; col[sq[i] - 'A'] = i % 5; }
        }
        char at(int r, int c) const { return sq[(r + 5) % 5 * 5 + (c + 5) % 5]; }
    
        // d = 1 encrypts, d = -1 decrypts. The text must already be split into valid pairs.
        string run(const string& text, int d) const {
            string out;
            for (size_t i = 0; i + 1 < text.size(); i += 2) {
                int ra = row[text[i] - 'A'], ca = col[text[i] - 'A'];
                int rb = row[text[i + 1] - 'A'], cb = col[text[i + 1] - 'A'];
                if (ra == rb)      { out += at(ra, ca + d); out += at(rb, cb + d); }
                else if (ca == cb) { out += at(ra + d, ca); out += at(rb + d, cb); }
                else               { out += at(ra, cb);     out += at(rb, ca); }
            }
            return out;
        }
    };
    
    int main() {
        Playfair pf("MONARCHY");
        string c = pf.run("INSTRUMENTSX", 1);       // pairs: IN ST RU ME NT SX
        cout << c << '\n';                          // GATLMZCLRQXA
        cout << pf.run(c, -1) << '\n';              // INSTRUMENTSX
    }

    Common mistakes

    • Not skipping repeated key letters. MONARCHY has only 8 letters and no repeats, but a key like BALLOON puts B, A, L, O, N in the square, not B, A, L, L, O, O, N.
    • Forgetting the I/J cell. The square must have exactly 25 letters. If yours has 26, J got its own cell.
    • Splitting first and inserting X later. Insert fillers while splitting from the left: BALLOON is BA LX LO ON, not BA LL OO N with fillers added afterwards.
    • Mixing up the rectangle corners. Each letter keeps its own row and takes the other letter’s column. Swapping rows instead gives the wrong letters.
    • Moving left to encrypt. Encrypt moves right and down; decrypt moves left and up.

    Complexity at a glance

    Case / operationTimeWhy
    Building the key squareO(1)At most 26 letters to place.
    Encrypting or decrypting n lettersO(n)Keep a table of each letter's row and column.
    Possible key squares25! ≈ 1.6 × 10²⁵Far too many to try one by one.
    Different letter pairs25 × 24 = 600Pair-frequency analysis needs much more text than letter counting.

    Quick check

    Test yourself — pick an answer to see if you got it.

    1. With the key MONARCHY, what is the first row of the Playfair square?

    2. How is the plaintext BALLOON split into pairs?

    3. Using the MONARCHY square, what does the pair AR encrypt to?

    4. Why do I and J share a cell?

    5. If the pair AB encrypts to XY with the rectangle rule, what does BA encrypt to?

    Saved in this browser.
    Spotted a mistake or a bug in the 3D model?

    Report a mistake

    in Playfair Cipher. Thank you — every report makes the lesson better for the next reader.

    We'll also include a link to the step of the 3D model you're on and your browser type, so we can reproduce it.