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:
- Build a keyed Polybius square.
- Convert the plaintext and additive key into coordinates from that square.
- 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:
- Estimate the repeated key's period.
- Split the ciphertext into columns by key position.
- Test subtractions that leave valid Polybius coordinates.
- Compare the resulting streams with expected language frequencies.
- 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.
Related ciphers
| 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.