Old pencil and paper cryptosystems (UPDATED).

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

UPDATE: I just released v0.4.1 of old-crypto-rs, adding a new VIC Cipher derivative called SECOM, and a fixed implementation of the former. After reading KAHN 84, I realised that the original article I used to implement the VIC Ciper (and the Wikipedia page too BTW) was missing one important step done on the plaintext before going through the stradding checkerboard.

So you can get the latest one here.

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

and even this one:

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))
    }

URLs