Chaocipher

From Rosetta Code
Revision as of 17:30, 24 April 2018 by PureFox (talk | contribs) (Added new draft task : Chaocipher and added Kotlin implementation.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Chaocipher is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Description

The Chaocipher was invented by J.F.Byrne in 1918 and, although simple by modern cryptographic standards, does not appear to have been broken until the algorithm was finally disclosed by his family in 2010.

The algorithm is described in this paper by R.Moshe in 2010 and there is a C# implementation here.


Task

The task is to code the algorithm in your language and to test that it works with the plaintext 'WELLDONEISBETTERTHANWELLSAID' used in the paper itself.


Kotlin

This is based on the C# implementation referred to in the task description. <lang scala>// Version 1.2.40

object Chao {

   private val lAlphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
   private val rAlphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
   fun encrypt(plainText: String, showSteps: Boolean = false): String {
       var left  = lAlphabet
       var right = rAlphabet
       val cText = CharArray(plainText.length)
       val temp  = CharArray(26)
       for (i in 0 until plainText.length) {
           if (showSteps) println("$left  $right")
           val index = right.indexOf(plainText[i])
           cText[i] = left[index]
           if (i == plainText.length - 1) break
           // permute left
           for (j in index..25) temp[j - index] = left[j]
           for (j in 0 until index) temp[26 - index + j] = left[j]
           var store = temp[1]
           for (j in 2..13) temp[j - 1] = temp[j]
           temp[13] = store
           left = String(temp)
           // permute right
           for (j in index..25) temp[j - index] = right[j]
           for (j in 0 until index) temp[26 - index + j] = right[j]
           store = temp[0]
           for (j in 1..25) temp[j - 1] = temp[j]
           temp[25] = store
           store = temp[2]
           for (j in 3..13) temp[j - 1] = temp[j]
           temp[13] = store
           right = String(temp)
       }
       return String(cText)
   }
   fun decrypt(cipherText: String, showSteps: Boolean = false): String {
       var left  = lAlphabet
       var right = rAlphabet
       val pText = CharArray(cipherText.length)
       val temp  = CharArray(26)
       for (i in 0 until cipherText.length) {
           if (showSteps) println("$left  $right")
           val index = left.indexOf(cipherText[i])
           pText[i] = right[index]
           if (i == cipherText.length - 1) break
           // permute left
           for (j in index..25) temp[j - index] = left[j]
           for (j in 0 until index) temp[26 - index + j] = left[j]
           var store = temp[1]
           for (j in 2..13) temp[j - 1] = temp[j]
           temp[13] = store
           left = String(temp)
           // permute right
           for (j in index..25) temp[j - index] = right[j]
           for (j in 0 until index) temp[26 - index + j] = right[j]
           store = temp[0]
           for (j in 1..25) temp[j - 1] = temp[j]
           temp[25] = store
           store = temp[2]
           for (j in 3..13) temp[j - 1] = temp[j]
           temp[13] = store
           right = String(temp)
       }
       return String(pText)
   }

}

fun main(args: Array<String>) {

   val plainText = "WELLDONEISBETTERTHANWELLSAID"
   println("The original plaintext is : $plainText")
   println("\nThe left and right alphabets after each permutation" +
           " during encryption are :\n")
   val cipherText = Chao.encrypt(plainText, true)
   println("\nThe ciphertext is : $cipherText")
   val plainText2 = Chao.decrypt(cipherText)
   println("\nThe recovered plaintext is : $plainText2")

}</lang>

Output:
The original plaintext is : WELLDONEISBETTERTHANWELLSAID

The left and right alphabets after each permutation during encryption are :

HXUCZVAMDSLKPEFJRIGTWOBNYQ  PTLNBQDEOYSFAVZKGJRIHWXUMC
ONYQHXUCZVAMDBSLKPEFJRIGTW  XUCPTLNBQDEOYMSFAVZKGJRIHW
ADBSLKPEFJRIGMTWONYQHXUCZV  OYSFAVZKGJRIHMWXUCPTLNBQDE
HUCZVADBSLKPEXFJRIGMTWONYQ  NBDEOYSFAVZKGQJRIHMWXUCPTL
QUCZVADBSLKPEHXFJRIGMTWONY  NBEOYSFAVZKGQDJRIHMWXUCPTL
HFJRIGMTWONYQXUCZVADBSLKPE  JRHMWXUCPTLNBIEOYSFAVZKGQD
CVADBSLKPEHFJZRIGMTWONYQXU  YSAVZKGQDJRHMFWXUCPTLNBIEO
NQXUCVADBSLKPYEHFJZRIGMTWO  BIOYSAVZKGQDJERHMFWXUCPTLN
YHFJZRIGMTWONEQXUCVADBSLKP  RHFWXUCPTLNBIMOYSAVZKGQDJE
NQXUCVADBSLKPEYHFJZRIGMTWO  MOSAVZKGQDJERYHFWXUCPTLNBI
XCVADBSLKPEYHUFJZRIGMTWONQ  AVKGQDJERYHFWZXUCPTLNBIMOS
TONQXCVADBSLKWPEYHUFJZRIGM  IMSAVKGQDJERYOHFWZXUCPTLNB
SKWPEYHUFJZRILGMTONQXCVADB  RYHFWZXUCPTLNOBIMSAVKGQDJE
ZILGMTONQXCVARDBSKWPEYHUFJ  LNBIMSAVKGQDJOERYHFWZXUCPT
JILGMTONQXCVAZRDBSKWPEYHUF  LNIMSAVKGQDJOBERYHFWZXUCPT
RBSKWPEYHUFJIDLGMTONQXCVAZ  RYFWZXUCPTLNIHMSAVKGQDJOBE
RSKWPEYHUFJIDBLGMTONQXCVAZ  YFZXUCPTLNIHMWSAVKGQDJOBER
HFJIDBLGMTONQUXCVAZRSKWPEY  LNHMWSAVKGQDJIOBERYFZXUCPT
JDBLGMTONQUXCIVAZRSKWPEYHF  MWAVKGQDJIOBESRYFZXUCPTLNH
BGMTONQUXCIVALZRSKWPEYHFJD  VKQDJIOBESRYFGZXUCPTLNHMWA
YFJDBGMTONQUXHCIVALZRSKWPE  HMAVKQDJIOBESWRYFGZXUCPTLN
HIVALZRSKWPEYCFJDBGMTONQUX  RYGZXUCPTLNHMFAVKQDJIOBESW
QXHIVALZRSKWPUEYCFJDBGMTON  SWYGZXUCPTLNHRMFAVKQDJIOBE
KPUEYCFJDBGMTWONQXHIVALZRS  NHMFAVKQDJIOBRESWYGZXUCPTL
SPUEYCFJDBGMTKWONQXHIVALZR  NHFAVKQDJIOBRMESWYGZXUCPTL
OQXHIVALZRSPUNEYCFJDBGMTKW  WYZXUCPTLNHFAGVKQDJIOBRMES
UEYCFJDBGMTKWNOQXHIVALZRSP  GVQDJIOBRMESWKYZXUCPTLNHFA
JBGMTKWNOQXHIDVALZRSPUEYCF  OBMESWKYZXUCPRTLNHFAGVQDJI

The ciphertext is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY

The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID