liveBook · Manning

Substitution cipher

As explained in Julia as a Second Language

A substitution cipher is a cryptographic method that replaces each symbol in an alphabet with a corresponding symbol from another alphabet.

A substitution cipher replaces each letter in a message with the corresponding letter from a second alphabet. The ordinary alphabet supplies the letters to look up; the substitution alphabet supplies their replacements and acts as the secret key. Unlike a Caesar cipher, the key is not a rotation: it is the entire replacement alphabet. To exchange messages, both parties need the same mapping. section 15.4

In Julia, `join('A':'Z')` makes the ordinary alphabet, while `join(shuffle('A':'Z'))` makes a rearranged one. `zip` pairs their letters in order. For example, pairing `ABCDEF` with `ACFBDE` maps `B` to `C` and `C` to `F`. Collecting those pairs gives encryption and decryption a shared mapping. section 15.4.2

The same pairs work in both directions:

  • To encrypt, find the pair whose first letter matches the input and return its second letter. section 15.4.2
  • To decrypt, find the pair whose second letter matches the input and return its first letter. section 15.4.2
  • If a character is absent from the alphabet, leave it unchanged. section 15.4.2
Listing 15.8 Substitution cipher encryption based on an array lookup
using Random
 
alphabet = join('A':'Z')
substitute = join(shuffle('A':'Z'))
mapping = collect(zip(alphabet, substitute))
 
function substitution_encrypt(ch::Char, mapping::Vector)
    i = findfirst(row->first(row) == ch, mapping)    #1
    if isnothing(i)                                  #2
       ch
    else
       mapping[i][2]                                 #3
    end
end
 
function substitution_decrypt(ch::Char, mapping::Vector)
    i = findfirst(row->last(row) == ch, mapping)
    if isnothing(i)
       ch
    else
       mapping[i][1]
    end
end

The Julia listing puts forward and reverse lookup side by side, using `findfirst` on one vector of letter pairs. section 15.4.2

That mapping can be packaged in two ways. A `SubstitutionCipher` object can hold it and provide `encrypt` and `decrypt` methods. Alternatively, partially applied functions can capture it and return message-encryption and message-decryption functions. Both approaches let a password-keeping example exchange a substitution cipher for a Caesar cipher without rewriting the keeper. section 15.6 section 15.7.3

Encrypt and recover a message

With a generated mapping, `"HELLO" |> substitution_encrypt(mapping)` produces `"NEPPR"` in the shown run. Piping that result through `substitution_decrypt(mapping)` returns `"HELLO"`. The output depends on the shuffled alphabet; successful recovery depends on reusing the mapping. section 15.7.2

How Julia as a Second Language covers it

How deep it goes
Builds the alphabet mapping and works through character lookup, reverse lookup, object methods, and partially applied message functions.
Examples
Uses shuffled Julia alphabets, a paired-letter mapping, a message round trip, and password storage and retrieval.
What it assumes
Assumes some familiarity with Julia arrays and ranges while demonstrating `shuffle`, `zip`, and paired lookup.
What you can do after
Build it from scratch in Julia, then plug its encryption and decryption into either cipher-compatible password-keeper design.
How it connects
Connects substitution ciphers to Caesar ciphers, symmetric encryption, abstract interfaces, closures, and password-keeping services.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Julia as a Second Language. The section links point to the parts of the book it draws on.