# Cipher: Polybius' checkerboard

The Polybius Checkerboard, named after Greek historian Polybius, is an example of a **substitution cipher** from around 205-123 B.C. .

Polybius was the first to propose a method of substituting different two-digit numbers for a letter in an alphabet. Hence, the Polybius’ Checkerboard is an early example of a **substitution cipher**.

## Polybius’ Checkerboard

A Polybius’ checkerboard looks almost like a like a **checkerboard**.
Each square holds a letter and we can locate a letter on the checkerboard by crossreferencing a unique row and column number.

Thus, each letter is represented by a number pair $(n,m)$, where the first number in the pair represents the **row**, and the second number in the pair represents the **column** on the checkerboard.
If we does this for the **Roman** alphabet we get something like this:

In the checkerboard above, the letter $S$ is located on row 4 and column 3, so its representation is $(4,3)$.

Please not the exception in row-column (2,4) which holds two letters

I/J.

## The Polybius Ciphering Process

Using a Polybius’ Checkerboard, we can encipher a *plaintext* message by **substituting** each letter in the message with a number pair representing the letter’s position on the board.

For example, *enciphering* the plaintext message:
$$“SENDMORETROOPS”$$

results in the ciphertext:

$$4315331432344215444234343543$$

The *deciphering* process would mean **reverting** the ciphering process, *translating* each number pair to its location o the checkerboard.

Russian Nihilist political prisoners are believed to have adapted a Polybius Checkerboard system to communicate secretly across prison cell walls.

## A Simple Code Example

Let’s try to write a simple **Polybius’ Checkerboard** cipher program.

The following program makes a lot of assumptions on the input provided to the ciphering function. The program is only meant to illustrate the fundamental idea of the cipher.

```
1pub struct Checkerboard {
2 rows: [[char; 5]; 5],
3}
4
5impl Checkerboard {
6 /// Creates a new Polybius Checkerboard, preloaded with the Roman alphabet.
7 pub fn new() -> Self {
8 Checkerboard {
9 rows:
10 [['A','B','C','D','E'],
11 ['F','G','H','I','K'],
12 ['L','M','N','O','P'],
13 ['Q','R','S','T','U'],
14 ['V','W','X','Y','Z']]}
15 }
16
17 pub fn get(&self, row: usize, col: usize) -> Option<char> {
18 let val = self.rows.get(row)?.get(col)?;
19 Some(*val)
20 }
21
22 /// OBS! We increment the ith and jth value to adjust for
23 /// the common practice of starting a checkerboard index by
24 /// the values 1 (instead of 0, which is common in computer
25 /// science). Thus, the letter 'A' has the adjusted index of
26 /// (1,1) instead of (0,0).
27 pub fn get_position(&self, searchletter:char) -> Option<String> {
28 let mut res = String::new();
29 for (i, row) in self.rows.iter().enumerate() {
30 for (j, letter) in row.iter().enumerate() {
31 if letter == &searchletter {
32 res = (i+1).to_string();
33 res.push_str(&(j+1).to_string());
34 }
35 }
36 }
37 Some(res)
38 }
39
40 pub fn encipher(&self, plaintext: &str) -> String {
41 let mut ciphertext = String::new();
42 for c in plaintext.chars() {
43 ciphertext.push_str(&self.get_position(c).unwrap());
44 }
45
46 ciphertext
47 }
48}
49
50fn main() {
51 let checkerboard = Checkerboard::new();
52 println!("SENDMORETROOPS = {}", checkerboard.encipher("SENDMORETROOPS"));
53}
54
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn encipher_test() {
62 let roman_checkerboard= Checkerboard::new();
63 assert_eq!(roman_checkerboard.encipher("SENDMORETROOPS"),
64 "4315331432344215444234343543");
65 }
66}
```