I posted a Swift project to GitHub that implements the Caesar cipher, which was the encryption technique used to protect Julius Caesar’s personal correspondence. It’s a straightforward algorithm that maps each letter in the alphabet to another letter.
The code also shows how to break, or “crack”, an enciphered message using basic statistical analysis.
ENCIPHER -> FODJQIFS
Here are a couple of the unit tests in the CaesarCipherTests class, showing the expected output based on the input string and shift-by argument:
Here is how the encipher method in CaesarCipher works:
The Letters type seen in that code example is a trivial utility struct that simplifies working with an individual letter as its numeric character code. Unfortunately working with individual characters like this in Swift is cumbersome, because of the way Swift supports Unicode text. To treat an individual letter as its character code requires using the UnicodeScalar type, whose value property returns 65 for A, 66 for B, etc.
EFDJQIFS -> DECIPHER
The decipher method is more complicated than its encipher counterpart. It uses statistical analysis to search for the letter mapping that, when applied to the enciphered text, best matches the expected letter frequencies in a written language’s words (English words, in my case). The statistical tool used to calculate the degree of difference between the observed (O) and expected (E) distributions is known as Pearson’s chi-squared test.
The core idea in the decipher method is to try all 26 possible character mappings and find the one whose relative letter frequencies most closely match the expected letter frequencies. The expected frequencies are calculated on-the-fly, by analyzing a list of English words included in OS X. The LetterFrequency class is responsible for that.
These unit tests from CaesarCipherTests show what to expect from the decipher method, including the fact that it cannot decrypt all messages (especially very short ones).
Here’s how the decipher method in CaesarCipher works…