Old pencil and paper cryptosystems.
Table of Contents
As you may have seen from my site, I have long been interested in old pencil and paper cryptosystems, even before getting hooked on computers. Over the years, I have re-implemented a few of them in various languages:
- Old BASIC on my Sinclair QL like ages ago
- Like 15 years ago in Ruby
- Then in Go when I learned the language in 2016
- And more recently in, what else, Rust
Cipher List
In order of complexity, here are the systems implemented:
- Caesar (yes, Julius Caesar himself), a simple substitution cipher
- Basic Transposition cipher, basic columnar one, mostly used as part of others because it is too simple
- A basic Polybius square cipher from ancient Greece
- Playfair cipher , created by Sir Charles Wheatstone but popularised by the Baron Playfair
- A more complex square cipher, using frequency analysis to shorten the ciphertext and complicate cryptanalysis, called the Straddling checkerboard
- The Wheatstone cipher machine, a mechanical device for encryption and decryption invented by the same Charles Wheatstone
- Chaocipher , a simple cipher machine invented by John Francis Byrne in 1918
and some more complex ones, using some above to add superencipherement like
- ADFGVX cipher , used by the German Army during WWI, finally broken in time by Georges Painvin in 1918
- The Nihilist Cipher used by the Russian Nihilist in the 1880s against the Tsar
- The VIC cipher , a more complex one used by Soviets during the Cold War
- The SIGABA Cipher Machine , created by the US Signal Intelligence Service during WWII, more complex than the German Enigma Machine .
and even this one:
- Solitaire , a card-based simple stream cipher invented by Bruce Schneier for Neal Stephenson’s book, The Cryptonomicon
Usage
It is fairly easy to use, just look into the examples/demo.rs file.
use old_crypto::{Block, ADFGVX};
let c = ADFGVX::new("CIPHER", "MACHINE");
let plaintext = "THISISANEXAMPLE".to_string();
let mut ct = vec![];
let n = c.encrypt(&mut ct, plaintext.as_bytes())?;
let ciphertext = String::from_utf8(ct)?;
println!("{plaintext} => {ciphertext}"); The Go example is even simpler:
package main
import (
"fmt"
"github.com/keltia/cipher"
"github.com/keltia/cipher/adfgvx"
)
func main() {
c, _ := adfgvx.New("CIPHER", "MACHINE")
plaintext := "THISISANEXAMPLE"
dst := make([]byte, len(plaintext) * 2)
c.Encrypt(dst, []byte(plaintext))
fmt.Printf("%s => %s\n", plaintext, string(dst))
}