Skip to content
Also from us: TypologyOnline.com · Free personality tests

Nihilist Cipher: Polybius Squares, Repeated Keys, and Number Codes

How a simple 5×5 letter square became a numerical cipher with two keys, repeated addition, and a revolutionary history.

Try the Nihilist Cipher tool
Illustration of Polybius coordinates and a repeated key combining into Nihilist cipher numbers
The Nihilist cipher adds repeated key coordinates to plaintext coordinates from the same keyed Polybius square.

The Nihilist cipher is a classical hand cipher that turns letters into Polybius-square coordinates, then hides those coordinates by adding values from a repeated key. Its ciphertext is a stream of numbers rather than disguised letters, but the mechanism remains wonderfully mechanical: build a square, convert the message and key into the same number system, then add.

What is the Nihilist cipher?

A Polybius square assigns every letter a row-and-column coordinate such as 11, 24, or 53. The Nihilist cipher adds a second layer: it converts an additive keyword through the same square and adds the resulting key coordinate to each plaintext coordinate.

The core rule is:

$$C_i = P_i + K_i$$

Here, $P_i$ is the plaintext coordinate, $K_i$ is the repeated key coordinate, and $C_i$ is the ciphertext number at position $i$. Instead of alphabetic ciphertext such as KHOOR, the result looks like this:

29 96 89 59 52 47 / 29 96 / 66 59 84 50

This is a Polybius-square substitution cipher with additive over-encryption. It is not secure by modern standards, but it is excellent for seeing how classical systems can be layered and how a repeated key can hide simple substitution without removing all of its patterns.

At a glance

Feature Nihilist Cipher
Cipher type Polybius-square substitution with additive over-encryption
Main idea Convert plaintext and key letters into coordinates, then add them
Encryption $C_i = P_i + K_i$
Decryption $P_i = C_i - K_i$
Keys A square keyword and an additive keyword
Common grid 5×5
I/J rule I and J usually share one cell
Output Numbers rather than letters
Security today Educational only
Best for Learning coordinate ciphers, repeated keys, and over-encryption

How the cipher works

The classical process has three stages:

  1. Build a keyed Polybius square.
  2. Convert the plaintext and additive key into coordinates from that square.
  3. Add each plaintext coordinate to the matching repeated key coordinate.

For example, if the square gives A = 15 and R = 14, then:

15 + 14 = 29

So plaintext A beneath key letter R becomes ciphertext number 29. That one calculation contains the entire encryption rule.

Step 1: Build the Polybius square

A 5×5 grid has 25 cells, so the common English-language version merges I and J. Begin with a square keyword—here, ZEBRA—remove repeated letters, then append unused letters of the alphabet while omitting J as a separate cell.

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

The row is written first and the column second. Useful values from this square include:

Letter Coordinate
Z 11
E 12
A 15
C 21
I/J 31
T 45
W 53

Thus T = 45 because T sits in row 4, column 5. Changing the square keyword changes these mappings and therefore changes every later calculation.

Step 2: Convert the additive key

The additive key is separate from the square keyword. With additive key RUSSIA, the same square produces:

Key letter Coordinate
R 14
U 51
S 44
S 44
I 31
A 15

The numeric key stream is therefore:

14 51 44 44 31 15

It repeats for as long as the message continues:

R U S S I A R U S S I A ...
14 51 44 44 31 15 14 51 44 44 31 15 ...

This resembles the repeated-key idea behind Vigenère, but Nihilist uses two-digit Polybius coordinates and ordinary addition rather than alphabet positions modulo 26.

Step 3: Add the two number streams

For each plaintext letter, look up the plaintext coordinate and the coordinate of the matching key letter, then add them:

Plaintext A = 15
Key letter R = 14
Ciphertext  = 15 + 14 = 29

The key advances only when a plaintext letter is processed. Spaces and punctuation normally do not consume key positions.

Worked example: encrypting ATTACK AT DAWN

Encrypt ATTACK AT DAWN using square keyword ZEBRA and additive keyword RUSSIA. For the calculation, the plaintext letters and repeated key are:

Plaintext: ATTACKATDAWN
Key:       RUSSIARUSSIA
Step Plain Plain value Key Key value Calculation Cipher number
1 A 15 R 14 15 + 14 29
2 T 45 U 51 45 + 51 96
3 T 45 S 44 45 + 44 89
4 A 15 S 44 15 + 44 59
5 C 21 I 31 21 + 31 52
6 K 32 A 15 32 + 15 47
7 A 15 R 14 15 + 14 29
8 T 45 U 51 45 + 51 96
9 D 22 S 44 22 + 44 66
10 A 15 S 44 15 + 44 59
11 W 53 I 31 53 + 31 84
12 N 35 A 15 35 + 15 50

With slashes marking the original word breaks, the ciphertext is:

29 96 89 59 52 47 / 29 96 / 66 59 84 50

Without those optional markers, it is simply:

29 96 89 59 52 47 29 96 66 59 84 50

Slashes are display aids rather than part of the arithmetic. Removing them hides word lengths, although it also means the receiver must reconstruct spaces from context.

How to decrypt it

Decryption reverses the addition:

$$P_i = C_i - K_i$$

If the ciphertext number is 29 and the matching key letter is R = 14, then:

29 - 14 = 15
15 = A

The first six values from the worked example reverse like this:

Cipher number Key Key value Calculation Plain value Plain letter
29 R 14 29 - 14 15 A
96 U 51 96 - 51 45 T
89 S 44 89 - 44 45 T
59 S 44 59 - 44 15 A
52 I 31 52 - 31 21 C
47 A 15 47 - 15 32 K

So 29 96 89 59 52 47 decrypts to ATTACK. If subtraction produces something outside the valid Polybius coordinates—such as 67—the key, square, or ciphertext is wrong.

Key and formatting rules

The square keyword controls every coordinate

ZEBRA, CIPHER, and FORTIFICATION all create different letter arrangements. The same message and additive key therefore produce different ciphertext under different square keywords.

The additive key repeats across letters

For ATTACKATDAWN, key RUSSIA repeats as RUSSIARUSSIA. Spaces and punctuation are skipped rather than consuming positions in the key stream.

I and J share a cell

The usual 5×5 square treats J as I. A plaintext J therefore normally decrypts as I; the distinction has been lost before addition even begins.

Ciphertext is numeric

Unlike Caesar, Atbash, Vigenère, or Beaufort, Nihilist produces sums such as 29, 96, and 89. Some sums can contain three digits because the largest coordinate addition is 55 + 55 = 110.

Word breaks are optional

Keeping / markers makes teaching examples easier to follow, but it exposes word lengths. Removing them produces a more historically cautious number stream at the cost of readability.

Why is it called the Nihilist cipher?

The name comes from the cipher's association with Russian Nihilist revolutionaries in the late nineteenth century. Its lasting value, however, is structural rather than dramatic: it demonstrates how a coordinate substitution can be over-encrypted with a second repeated key.

The label is sometimes applied more broadly to later numerical hand-cipher systems, including more elaborate espionage methods. This article focuses on the classical Nihilist substitution cipher used in lessons, puzzles, and modern cipher tools: a keyed Polybius square followed by repeated coordinate addition.

Why it was useful

For a pencil-and-paper system, Nihilist offered several practical advantages:

Advantage Why it mattered
Usable by hand No machine was required
Numerical output The message no longer resembled ordinary disguised text
Two-key structure One keyword controlled the square and another the additive stream
Stronger than plain Polybius A plaintext letter could produce different visible numbers
Mechanical procedure Once both keys were known, encryption and decryption were routine

A plain Polybius square always maps one letter to one coordinate. With the square above, A always equals 15. Nihilist changes its visible result according to the repeated key:

A + R = 15 + 14 = 29
A + S = 15 + 44 = 59

The same plaintext letter can therefore produce different ciphertext numbers at different key positions.

Weaknesses

The cipher's main weakness is the periodic additive key. If the key is RUSSIA, every sixth plaintext letter is encrypted with the same key coordinate. Positions 1, 7, 13, 19... share the first key value; positions 2, 8, 14, 20... share the second; and so on.

Weakness Why it matters
Repeated key Ciphertext can be separated into streams by key position
Short key Frequent repetition makes periodic patterns stronger
Known plaintext A known plaintext coordinate immediately reveals a key coordinate
Restricted coordinates Valid plaintext coordinates use only row and column digits 1–5
I/J merging Some plaintext information is permanently lost
Preserved word breaks Word lengths help identify likely plaintext
Key reuse Multiple messages under the same keys provide more evidence

Nihilist hides simple letter frequencies better than a monoalphabetic substitution, but it does not eliminate statistical structure. It redistributes that structure into periodic numeric streams.

How it can be broken

If the additive key has length 6, write the ciphertext into six columns:

1   2   3   4   5   6
7   8   9   10  11  12
13  14  15  16  17  18
...

Every value in a column was produced with the same key coordinate. A classical attack can therefore:

  1. Estimate the repeated key's period.
  2. Split the ciphertext into columns by key position.
  3. Test subtractions that leave valid Polybius coordinates.
  4. Compare the resulting streams with expected language frequencies.
  5. Use likely words, known phrases, or other cribs to recover key values.

The attack becomes easier when the key is short, keys are reused, messages are long, word breaks remain visible, or some plaintext can be guessed.

A tiny known-plaintext attack

Suppose an attacker knows that the first plaintext letter is A, the first ciphertext number is 29, and the square gives A = 15. The first key coordinate follows immediately:

29 - 15 = 14

In the example square, 14 = R, so the attacker has recovered the first additive key letter. Enough known positions can reveal the repeating key, which is why predictable message openings and reused keys are dangerous.

Cipher Relationship to Nihilist
Polybius Square The foundation: letters become row-and-column coordinates
Vigenère Uses a similar repeated-key idea with alphabet values modulo 26
Beaufort Another repeated-key system with a different plaintext/key relationship
Bifid Uses Polybius coordinates but mixes rows and columns through fractionation
ADFGX / ADFGVX Combines a Polybius-style grid with transposition
One-time pad Adds a key stream securely only when it is random, message-length, secret, and never reused

Nihilist is a bridge between coordinate ciphers and repeated-key ciphers:

Polybius:  letter → coordinate
Vigenère: plaintext value + key value mod 26 → letter
Nihilist: plaintext coordinate + key coordinate → number

Where it appears today

Nihilist is now found in recreational cryptography, puzzle hunts, escape rooms, geocaching, classroom projects, codebreaking competitions, programming tutorials, and interactive cipher tools. It teaches several useful principles at once: letters can become coordinates, keys can share the message's number system, encryption can be layered, and repeated keys create exploitable patterns.

A page of numbers may look more formidable than a Caesar shift, but appearance is not security. The important question is always what information the system still reveals.

Python implementation

This educational implementation follows the same ZEBRA / RUSSIA conventions as the interactive tool. It supports a keyed 5×5 square, I/J merging, numerical ciphertext, and optional slash markers for word breaks.

Python exampleShow code
BASE_ALPHABET = "ABCDEFGHIKLMNOPQRSTUVWXYZ"  # J is omitted


def clean_letters(text):
    """Keep ASCII letters, uppercase them, and merge J into I."""
    letters = []

    for char in text.upper():
        if "A" <= char <= "Z":
            letters.append("I" if char == "J" else char)

    return "".join(letters)


def build_square(keyword):
    """Build a keyed 5x5 Polybius square."""
    seen = set()
    square = []

    for char in clean_letters(keyword) + BASE_ALPHABET:
        if char not in seen:
            seen.add(char)
            square.append(char)

    return square[:25]


def build_maps(square):
    """Create letter-to-coordinate and coordinate-to-letter maps."""
    letter_to_coord = {}
    coord_to_letter = {}

    for index, letter in enumerate(square):
        row = index // 5 + 1
        column = index % 5 + 1
        coordinate = row * 10 + column

        letter_to_coord[letter] = coordinate
        coord_to_letter[coordinate] = letter

    letter_to_coord["J"] = letter_to_coord["I"]
    return letter_to_coord, coord_to_letter


def encrypt(plaintext, square_keyword, additive_key, mark_words=True):
    """Encrypt plaintext with the Nihilist cipher."""
    square = build_square(square_keyword)
    letter_to_coord, _ = build_maps(square)
    key = clean_letters(additive_key)

    if not key:
        raise ValueError("The additive key must contain at least one letter.")

    output = []
    key_index = 0
    last_output_was_break = False

    for char in plaintext:
        upper = char.upper()

        if len(upper) == 1 and "A" <= upper <= "Z":
            plain_letter = "I" if upper == "J" else upper
            key_letter = key[key_index % len(key)]
            plain_value = letter_to_coord[plain_letter]
            key_value = letter_to_coord[key_letter]

            output.append(str(plain_value + key_value))
            key_index += 1
            last_output_was_break = False
        elif char.isspace() and mark_words and output and not last_output_was_break:
            output.append("/")
            last_output_was_break = True

    if output and output[-1] == "/":
        output.pop()

    return " ".join(output)


def decrypt(ciphertext, square_keyword, additive_key):
    """Decrypt space-separated Nihilist numbers."""
    square = build_square(square_keyword)
    letter_to_coord, coord_to_letter = build_maps(square)
    key = clean_letters(additive_key)

    if not key:
        raise ValueError("The additive key must contain at least one letter.")

    output = []
    key_index = 0

    for part in ciphertext.split():
        if part == "/":
            output.append(" ")
            continue

        cipher_value = int(part)
        key_letter = key[key_index % len(key)]
        key_value = letter_to_coord[key_letter]
        plain_value = cipher_value - key_value

        output.append(coord_to_letter.get(plain_value, "?"))
        key_index += 1

    return "".join(output).strip()


plaintext = "ATTACK AT DAWN"
square_keyword = "ZEBRA"
additive_key = "RUSSIA"

ciphertext = encrypt(plaintext, square_keyword, additive_key)
recovered = decrypt(ciphertext, square_keyword, additive_key)

print("Plaintext :", plaintext)
print("Encrypted :", ciphertext)
print("Decrypted :", recovered)

Expected output:

Plaintext : ATTACK AT DAWN
Encrypted : 29 96 89 59 52 47 / 29 96 / 66 59 84 50
Decrypted : ATTACK AT DAWN

The essential encryption line is output.append(str(plain_value + key_value)); decryption reverses it with plain_value = cipher_value - key_value. The mathematics and code line up almost perfectly, which makes Nihilist a particularly useful teaching cipher.

Common questions

Is the Nihilist cipher secure?

No. It is appropriate for education, puzzles, and historical study, not passwords, private messages, financial details, or personal data.

Why does it use numbers?

Both plaintext and key letters are first represented as Polybius row-and-column coordinates. Adding those coordinates naturally produces numeric ciphertext.

Is it the same as a Polybius square?

No. Polybius supplies the first layer, letter → coordinate. Nihilist adds a repeated key coordinate to each plaintext coordinate.

Why are I and J combined?

A 5×5 grid has 25 cells for a 26-letter alphabet. The common convention gives I and J the same cell, so J is treated as I.

Does it need two keys?

Usually. One keyword mixes the Polybius square and the other creates the repeated additive stream. Simplified variants may keep a standard square and use only the additive key.

What happens with the wrong key?

Subtraction produces nonsense letters or invalid coordinates. A tool can display invalid results as ? because no cell exists for values such as 67 in a 5×5 square.

Why is this called over-encryption?

The plaintext is first transformed into Polybius coordinates and then hidden again under an additive key stream. The second transformation is layered over the first.

The real lesson

Nihilist earns its place in cryptographic education because it shows how a simple substitution becomes more interesting when another layer is added. It also shows why repeated keys are practical, tempting, and dangerous: a number stream may look intimidating while its period still leaks structure.

The strongest habit this cipher teaches is simple: always ask what the system still reveals.

Sources and further reading

Try the Nihilist Cipher Tool

Want to experiment with the idea in practice? Open the matching tool and try your own text.

Open Nihilist Cipher
Signal acquired

A note from the team

We build these tools because we love cryptography, encoding, and making difficult ideas easier to explore. If they've helped you, even a small coffee means the world to the project. Thank you!

Say thanks on Ko-fi

Read next

Coordinate Ciphers Polybius Square Cipher: Turning Letters into Coordinates How a 5×5 grid turned the alphabet into numbers, signals, and one of classical cryptography's most useful building blocks. Fractionation Bifid Cipher: When Coordinates Get Split Apart How the Polybius square became a fractionating cipher that mixed letters before turning them back into text. Polyalphabetic Vigenère Cipher: When Classical Cryptography Learned to Change Alphabets How a repeating keyword lets classical cryptography rotate among several alphabets instead of relying on one fixed substitution.
Back to all articles