← all posts
Posted on Sep 15, 2022

Cipher: Spartan Scytale

Credit:

Credit: FotoRieth

The Spartan Scytale was communication device used by the military of Sparta.
The Scytale is an example of a transposition cipher and it dates from around 500 B.C. .

The Ciphering Process

Image:

Image: Spartan Scytale

  1. Setup:
    The sender of the message takes a strip of parchement (paper) and wrapps it around a cylindrical rod.
  2. Write plaintext message:
    The sender writes the message line by line, and parallel to the rod’s axis.This way, successive letters in a word are spread out across successive turns of the parchment.
  3. Send Message:
    The sender removes the parchment from the rod. A messenger is tasked with delivering the strip (message) to the intended receiver.
    Any enemy intercepting the messenger, and examining the strip, would only see a strip of jumpled letters. Without the rod it’s hard to decipher the message.
  4. Decipher:
    The messenger delivers the strip to the receiver of the message. The receiver deciphers the message by wrapping the strip around a scytale of his own and can now read the plaintext message.

A Simple Code Example

Let’s try to write a simple Spartan Scytale 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.

 1
 2struct Scytale {
 3    turns: usize,
 4    lines: usize,
 5}
 6
 7impl Scytale {
 8    fn new(t: usize, l: usize) -> Self {
 9        Scytale {
10            turns: t,
11            lines: l,
12        }
13    }
14
15    fn encipher(&self, message: &str) -> String {
16        let mut scytale_strip: Vec<char> = Vec::with_capacity(message.len());
17        for _ in 0..message.len() {
18            scytale_strip.push('-');
19        }
20
21        let mut chars = message.chars();
22        for line in 0..self.lines {
23            for turn in 0..self.turns {
24                scytale_strip[turn * self.lines + line] = chars.next().unwrap();
25            }
26        }   
27
28        scytale_strip.into_iter().collect::<String>()
29    }
30
31    fn decipher(&self, ciphertext: &str) -> String {
32        let mut scytale_strip: Vec<char> = Vec::new();
33
34        for  line in 0..self.lines {
35            for (i, c) in ciphertext.chars().enumerate() {
36                if i % self.lines == line {
37                    scytale_strip.push(c);
38                }
39            }
40        }
41
42        scytale_strip.iter().collect::<String>()
43    }
44}
45
46fn main() {
47    let scytale = Scytale::new(5,3);
48    println!("{}", scytale.encipher("abcdefghijklmno"));
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54    #[test]
55    fn encipher_test() {
56        let scytale = Scytale::new(5,3);
57        assert_eq!(scytale.encipher("abcdefghijklmno"), "afkbglchmdinejo");
58    }
59    
60    #[test]
61    fn decipher_test() {
62        let scytale = Scytale::new(5,3);
63        assert_eq!(scytale.decipher("afkbglchmdinejo"), "abcdefghijklmno");
64    }
65}