## 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.

Pages: 1 2

### 5 Responses to “Chaocipher”

1. […] Praxis – Chaocipher By Remco Niemeijer In today’s Programming Praxis we have another cipher on our hands, called chaocipher. The provided Scheme […]

2. Remco Niemeijer said

```import Control.Arrow
import Data.List

seek :: Int -> [a] -> [a]
seek to = uncurry (flip (++)) . splitAt to

shift :: Int -> Int -> [a] -> [a]
shift from to = (\((a,b),c) -> a ++ seek 1 b ++ c) .
first (splitAt from) . splitAt to

cipher :: Eq a => Bool -> [a] -> [a] -> [a] -> [a]
cipher _ _ _ []     = []
cipher e l r (x:xs) = to !! i : cipher e (shift 1 14 \$ seek i l)
(shift 2 14 . shift 0 26 \$ seek i r) xs
where Just i = elemIndex x from
(from, to) = if e then (r, l) else (l, r)

encipher, decipher :: Eq a => [a] -> [a] -> [a] -> [a]
encipher = cipher True
decipher = cipher False
```
3. razvan said

My version, in Java:

```package chaocipher;

public class Chaocipher {

private final int SIZE;

public Chaocipher(String ciphertext, String plaintext) {
for(int i=0; i<ciphertext.length(); i++) {
}
SIZE = cipher.size();
}

public String encrypt(String text) {
StringBuilder sb = new StringBuilder();
for(int i=0; i<text.length(); i++) {
char plainChar = text.charAt(i);
char cipherChar = encrypt(plainChar);
sb.append(cipherChar);
rotateDisks(cipherChar, plainChar);
}
return sb.toString();
}

public String decrypt(String text) {
StringBuilder sb = new StringBuilder();
for(int i=0; i<text.length(); i++) {
char cipherChar = text.charAt(i);
char plainChar = decrypt(cipherChar);
sb.append(plainChar);
rotateDisks(cipherChar, plainChar);
}
return sb.toString();
}

private char encrypt(char ch) {
int i = plain.indexOf(ch);
return cipher.get(i);
}

private char decrypt(char ch) {
int i = cipher.indexOf(ch);
return plain.get(i);
}

private void rotateDisks(char cipherChar, char plainChar) {
int ind = cipher.indexOf(cipherChar);
for(int i=0; i<ind; i++) {
char ch = cipher.remove(0);
}
char ch = cipher.remove(1);

ind = plain.indexOf(plainChar);
for(int i=0; i<ind; i++) {
ch = plain.remove(0);
}
ch = plain.remove(0);
ch = plain.remove(2);
}
}
```

And the main class is:

```package chaocipher;

public class Main {

public static void main(String[] args) {
Chaocipher ch = new Chaocipher("HXUCZVAMDSLKPEFJRIGTWOBNYQ",
"PTLNBQDEOYSFAVZKGJRIHWXUMC");
System.out.println(ch.encrypt("WELLDONEISBETTERTHANWELLSAID"));
}

}
```

And the output is as expected, i.e. OAHQHCNYNXTSZJRRHJBYHQKSOUJY.

4. Charles said

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

5. 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.