Chaocipher
July 6, 2010
We begin with a function that shifts characters left in a sequence. Shift
preserves the beginning and ending portions of the sequence (either of which may be null, depending on the parameters) and cycles the middle portion using an auxiliary function cycle
:
(define (shift first past offset str)
(define (cycle str offset)
(append (drop offset str) (take offset str)))
(let ((str (string->list str)))
(list->string (append
(take first str)
(cycle (take (- past first) (drop first str)) offset)
(drop past str)))))
Then shift-left
and shift-right
apply the rules stated above:
(define (shift-left n str)
(shift 1 14 1
(shift 0 26 n str)))
(define (shift-right n str)
(shift 2 14 1
(shift 0 26 1
(shift 0 26 n str))))
The cipher
function loops through the input text, processing each character and shifting the two sequences. The enciphering?
flag chooses the appropriate disk:
(define (cipher left right enciphering? str)
(let loop ((old (string->list str))
(left left) (right right) (new '()))
(if (null? old)
(list->string (reverse new))
(let ((n (string-index (car old) (if enciphering? right left))))
(loop (cdr old) (shift-left n left) (shift-right n right)
(cons (string-ref (if enciphering? left right) n) new))))))
Given cipher
, the functions that actually perform enciphering and deciphering are trivial:
(define (encipher left right str) (cipher left right #t str))
(define (decipher left right str) (cipher left right #f str))
Here’s an example:
> (encipher ct pt "WELLDONEISBETTERTHANWELLSAID")
"OAHQHCNYNXTSZJRRHJBYHQKSOUJY"
> (decipher ct pt "OAHQHCNYNXTSZJRRHJBYHQKSOUJY")
"WELLDONEISBETTERTHANWELLSAID"
We used take
, drop
and string-index
from the Standard Prelude. You can run the program at http://programmingpraxis.codepad.org/W6om4hgd.
[…] Praxis – Chaocipher By Remco Niemeijer In today’s Programming Praxis we have another cipher on our hands, called chaocipher. The provided Scheme […]
My Haskell solution (see http://bonsaicode.wordpress.com/2010/07/06/programming-praxis-chaocipher/ for a version with comments):
My version, in Java:
And the main class is:
And the output is as expected, i.e. OAHQHCNYNXTSZJRRHJBYHQKSOUJY.
I am a student learning about encryption ciphers, and after attempting to run the java code above, I noticed the decrypt function does not work as expected. I have copied the source code directly from here, so there is no error in typing, and I will post the output of the decrypt function of the encryption of WELLDONEISBETTERTHANWELLSAID.
WELLDONEISBETTERTHANWELLSAID
OAHQHCNYNXTSZJRRHJBYHQKSOUJY
XHTJNNTWNDTWSBFVRGLSLSSCXAZY
HXUCZVAMDSLKPEFJRIGTWOBNYQ
PTLNBQDEOYSFAVZKGJRIHWXUMC
the first line is the line that was to be encrypted. the second line is what is to be expected from the encryption function. the third line is the unexpected result of the decryption function, and the fourth and fifth lines are the ciphertext and plaintext that are the arguments passed in through the Chaocipher object
I know this is old, but to answer Charles (and anyone else who comes along)…
To use the java solution one needs to create a second Chaocipher object for decryption. Alternatively you could do something weird like reset the cipher and plain texts after each encryption/decryption, but that sort of ruins the complexity of the thing.