Chaocipher: Difference between revisions
(Added Easylang) |
|||
(60 intermediate revisions by 28 users not shown) | |||
Line 1: | Line 1: | ||
{{task}} |
{{task}} |
||
;Description: |
|||
The [[wp:Chaocipher|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 [[wp:Chaocipher|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. |
||
Line 8: | Line 7: | ||
;Task: |
|||
Code the algorithm in your language and test that it works with the plaintext 'WELLDONEISBETTERTHANWELLSAID' used in the paper itself. |
|||
<br><br> |
|||
=={{header|11l}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="11l">F correct_case(string) |
|||
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. |
|||
R string.filter(s -> s.is_alpha()).map(s -> s.uppercase()).join(‘’) |
|||
F permu(String alp; num) |
|||
R alp[num..]‘’alp[0 .< num] |
|||
F rotate_wheels(lalph, ralph, key) |
|||
V newin = ralph.index(key) |
|||
R (permu(lalph, newin), permu(ralph, newin)) |
|||
F scramble_wheels(String =lalph, String =ralph) |
|||
lalph = lalph[0]‘’lalph[2.<14]‘’lalph[1]‘’lalph[14..] |
|||
ralph = ralph[1.<3]‘’ralph[4.<15]‘’ralph[3]‘’ralph[15..]‘’ralph[0] |
|||
R (lalph, ralph) |
|||
F do_chao(=msg, =lalpha, =ralpha, en = 1B, show = 0B) |
|||
msg = correct_case(msg) |
|||
V out = ‘’ |
|||
I show |
|||
print(‘=’ * 54) |
|||
print((10 * ‘ ’)‘left:’(21 * ‘ ’)‘right: ’) |
|||
print(‘=’ * 54) |
|||
print(lalpha‘ ’ralpha" \n") |
|||
L(l) msg |
|||
I en |
|||
(lalpha, ralpha) = rotate_wheels(lalpha, ralpha, l) |
|||
out ‘’= lalpha[0] |
|||
E |
|||
(ralpha, lalpha) = rotate_wheels(ralpha, lalpha, l) |
|||
out ‘’= ralpha[0] |
|||
(lalpha, ralpha) = scramble_wheels(lalpha, ralpha) |
|||
I show |
|||
print(lalpha‘ ’ralpha) |
|||
R out |
|||
V lalpha = ‘HXUCZVAMDSLKPEFJRIGTWOBNYQ’ |
|||
V ralpha = ‘PTLNBQDEOYSFAVZKGJRIHWXUMC’ |
|||
V msg = ‘WELLDONEISBETTERTHANWELLSAID’ |
|||
print(‘L: ’lalpha) |
|||
print(‘R: ’ralpha) |
|||
print(‘I: ’msg) |
|||
V o = do_chao(msg, lalpha, ralpha, 1B, 0B) |
|||
print(‘O: ’o) |
|||
print(‘D: ’do_chao(o, lalpha, ralpha, 0B, 0B)) |
|||
print() |
|||
do_chao(msg, lalpha, ralpha, 1B, 1B)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
L: HXUCZVAMDSLKPEFJRIGTWOBNYQ |
|||
R: PTLNBQDEOYSFAVZKGJRIHWXUMC |
|||
I: WELLDONEISBETTERTHANWELLSAID |
|||
O: OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
D: WELLDONEISBETTERTHANWELLSAID |
|||
====================================================== |
|||
left: right: |
|||
====================================================== |
|||
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 |
|||
YFJBGMTKWNOQXCHIDVALZRSPUE JIBMESWKYZXUCOPRTLNHFAGVQD |
|||
</pre> |
|||
=={{header|Ada}}== |
|||
This solution uses array slices to permute the left and right strings. Use of slices clarifies the looping logic. |
|||
Ada strings are indexed with the predefined subtype Positive which begins at 1. |
|||
<syntaxhighlight lang="ada"> |
|||
with Ada.Text_IO; use Ada.Text_IO; |
|||
procedure chao_slices is |
|||
type iMode is (Encrypt, Decrypt); |
|||
L_Alphabet : String := "HXUCZVAMDSLKPEFJRIGTWOBNYQ"; |
|||
R_Alphabet : String := "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
|||
plaintext : String := "WELLDONEISBETTERTHANWELLSAID"; |
|||
ciphertext : String (1 .. plaintext'length); |
|||
plaintext2 : String (1 .. plaintext'length); |
|||
offset : Natural; |
|||
function IndexOf (Source : String; Value : Character) return Positive is |
|||
Result : Positive; |
|||
begin |
|||
for I in Source'Range loop |
|||
if Source (I) = Value then |
|||
Result := I; |
|||
exit; |
|||
end if; |
|||
end loop; |
|||
return Result; |
|||
end IndexOf; |
|||
function Exec |
|||
(Text : String; mode : iMode; showsteps : Boolean := False) return String |
|||
is |
|||
etext : String (Text'First .. Text'Last); |
|||
temp : String (1 .. 26); |
|||
index : Positive; |
|||
store : Character; |
|||
left : String := L_Alphabet; |
|||
right : String := R_Alphabet; |
|||
begin |
|||
for I in Text'Range loop |
|||
if showsteps then |
|||
Put_Line (left & " " & right); |
|||
end if; |
|||
if mode = Encrypt then |
|||
index := IndexOf (Source => right, Value => Text (I)); |
|||
etext (I) := left (index); |
|||
else |
|||
index := IndexOf (Source => left, Value => Text (I)); |
|||
etext (I) := right (index); |
|||
end if; |
|||
exit when I = Text'Last; |
|||
-- permute left |
|||
-- The array value permutations are performed using array slices |
|||
-- rather than explicit loops |
|||
if index > 1 then |
|||
offset := 26 - index; |
|||
temp (1 .. offset + 1) := left (index .. index + offset); |
|||
temp (offset + 2 .. 26) := left (1 .. index - 1); |
|||
store := temp (2); |
|||
temp (2 .. 13) := temp (3 .. 14); |
|||
temp (14) := store; |
|||
left := temp; |
|||
-- permute right |
|||
-- The array value permutations are performed using array slices |
|||
-- rather than explicit loops |
|||
temp (1 .. offset + 1) := right (index .. index + offset); |
|||
temp (offset + 2 .. 26) := right (1 .. index - 1); |
|||
store := temp (1); |
|||
temp (1 .. 25) := temp (2 .. 26); |
|||
temp (26) := store; |
|||
store := temp (3); |
|||
temp (3 .. 13) := temp (4 .. 14); |
|||
temp (14) := store; |
|||
right := temp; |
|||
end if; |
|||
end loop; |
|||
return etext; |
|||
end Exec; |
|||
begin |
|||
Put_Line ("The original text is : " & plaintext); |
|||
New_Line; |
|||
Put_Line |
|||
("The left and right alphabets after each permutation during encryption are:"); |
|||
New_Line; |
|||
ciphertext := Exec (plaintext, Encrypt, True); |
|||
New_Line; |
|||
Put_Line ("The ciphertext is : " & ciphertext); |
|||
plaintext2 := Exec (ciphertext, Decrypt); |
|||
New_Line; |
|||
Put_Line ("The recovered plaintext is : " & plaintext2); |
|||
end chao_slices; |
|||
</syntaxhighlight> |
|||
{{output}} |
|||
<pre> |
|||
The original text 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 |
|||
RBSKWPEYHUFJIDLGMTONQXCVAZ RYFWZXUCPTLNIHMSAVKGQDJOBE |
|||
UJIDLGMTONQXCFVAZRBSKWPEYH LNHMSAVKGQDJOIBERYFWZXUCPT |
|||
ILGMTONQXCFVADZRBSKWPEYHUJ MSVKGQDJOIBERAYFWZXUCPTLNH |
|||
DRBSKWPEYHUJIZLGMTONQXCFVA YFZXUCPTLNHMSWVKGQDJOIBERA |
|||
HJIZLGMTONQXCUFVADRBSKWPEY HMWVKGQDJOIBESRAYFZXUCPTLN |
|||
ILGMTONQXCUFVZADRBSKWPEYHJ VKQDJOIBESRAYGFZXUCPTLNHMW |
|||
XUFVZADRBSKWPCEYHJILGMTONQ SRYGFZXUCPTLNAHMWVKQDJOIBE |
|||
WCEYHJILGMTONPQXUFVZADRBSK NAMWVKQDJOIBEHSRYGFZXUCPTL |
|||
KCEYHJILGMTONWPQXUFVZADRBS NAWVKQDJOIBEHMSRYGFZXUCPTL |
|||
PXUFVZADRBSKCQEYHJILGMTONW RYFZXUCPTLNAWGVKQDJOIBEHMS |
|||
KQEYHJILGMTONCWPXUFVZADRBS WGKQDJOIBEHMSVRYFZXUCPTLNA |
|||
LMTONCWPXUFVZGADRBSKQEYHJI BEMSVRYFZXUCPHTLNAWGKQDJOI |
|||
The ciphertext is : OAHQHCNYNXTSZJRRUIDHIXWKPKLY |
|||
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID |
|||
</pre> |
|||
=={{header|AppleScript}}== |
|||
<syntaxhighlight lang="applescript">-- Chaocipher algorithm by J.F.Byrne 1918. |
|||
on chaocipher(input, |key|, mode) |
|||
-- input: text to be enciphered or deciphered. |
|||
-- |key|: script object or record with leftAlpha and rightAlpha properties, each of whose values is a shuffled alphabet text. |
|||
-- mode: the text "encipher" or "decipher". |
|||
script o |
|||
property inputChars : input's characters |
|||
property leftAlpha : |key|'s leftAlpha's characters |
|||
property rightAlpha : |key|'s rightAlpha's characters |
|||
property inAlpha : leftAlpha |
|||
property outAlpha : rightAlpha |
|||
property output : {} |
|||
end script |
|||
set alphaLen to (count o's leftAlpha) |
|||
if ((count o's rightAlpha) ≠ alphaLen) then error |
|||
if (mode is "encipher") then |
|||
set {o's inAlpha, o's outAlpha} to {o's rightAlpha, o's leftAlpha} |
|||
else if (mode is not "decipher") then |
|||
error |
|||
end if |
|||
set zenith to 1 |
|||
set nadir to alphaLen div 2 + 1 |
|||
repeat with char in o's inputChars |
|||
set char to char's contents |
|||
set found to false |
|||
repeat with i from 1 to alphaLen |
|||
if (o's inAlpha's item i = char) then |
|||
set end of o's output to o's outAlpha's item i |
|||
set found to true |
|||
exit repeat |
|||
end if |
|||
end repeat |
|||
if (found) then |
|||
rotate(o's leftAlpha, zenith, alphaLen, -(i - zenith)) |
|||
rotate(o's leftAlpha, zenith + 1, nadir, -1) |
|||
rotate(o's rightAlpha, zenith, alphaLen, -i) |
|||
rotate(o's rightAlpha, zenith + 2, nadir, -1) |
|||
end if |
|||
end repeat |
|||
return join(o's output, "") |
|||
end chaocipher |
|||
on rotate(theList, l, r, amount) |
|||
set listLength to (count theList) |
|||
if (listLength < 2) then return |
|||
if (l < 0) then set l to listLength + l + 1 |
|||
if (r < 0) then set r to listLength + r + 1 |
|||
if (l > r) then set {l, r} to {r, l} |
|||
script o |
|||
property lst : theList |
|||
property storage : missing value |
|||
end script |
|||
set rangeLength to r - l + 1 |
|||
set amount to (rangeLength + rangeLength - amount) mod rangeLength |
|||
if (amount is 0) then return |
|||
set o's storage to o's lst's items l thru (l + amount - 1) |
|||
repeat with i from (l + amount) to r |
|||
set o's lst's item (i - amount) to o's lst's item i |
|||
end repeat |
|||
set j to r - amount |
|||
repeat with i from 1 to amount |
|||
set o's lst's item (j + i) to o's storage's item i |
|||
end repeat |
|||
end rotate |
|||
on join(lst, delim) |
|||
set astid to AppleScript's text item delimiters |
|||
set AppleScript's text item delimiters to delim |
|||
set txt to lst as text |
|||
set AppleScript's text item delimiters to astid |
|||
return txt |
|||
end join |
|||
-- Return a script object containing a couple of randomised alphabets to use as a choacipher key. |
|||
on makeKey() |
|||
set lAlpha to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"'s characters |
|||
copy lAlpha to rAlpha |
|||
script |key| |
|||
property leftAlpha : join(shuffle(lAlpha, 1, -1), "") |
|||
property rightAlpha : join(shuffle(rAlpha, 1, -1), "") |
|||
end script |
|||
return |key| |
|||
end makeKey |
|||
-- Fisher-Yates (aka Durstenfeld, aka Knuth) shuffle. |
|||
on shuffle(theList, l, r) |
|||
set listLength to (count theList) |
|||
if (listLength < 2) then return array |
|||
if (l < 0) then set l to listLength + l + 1 |
|||
if (r < 0) then set r to listLength + r + 1 |
|||
if (l > r) then set {l, r} to {r, l} |
|||
script o |
|||
property lst : theList |
|||
end script |
|||
repeat with i from l to (r - 1) |
|||
set j to (random number from i to r) |
|||
set v to o's lst's item i |
|||
set o's lst's item i to o's lst's item j |
|||
set o's lst's item j to v |
|||
end repeat |
|||
return theList |
|||
end shuffle |
|||
-- Demo using the two-alphabet key from the Rubin paper and another generated at random. |
|||
-- Decription must be with the key that was used for the encription. |
|||
on demo(originalText) |
|||
set key1 to {leftAlpha:"HXUCZVAMDSLKPEFJRIGTWOBNYQ", rightAlpha:"PTLNBQDEOYSFAVZKGJRIHWXUMC"} |
|||
set key2 to makeKey() |
|||
set enciphered to chaocipher(originalText, key1, "encipher") |
|||
set doubleEnciphered to chaocipher(enciphered, key2, "encipher") |
|||
set deDoubleEnciphered to chaocipher(doubleEnciphered, key2, "decipher") |
|||
set deciphered to chaocipher(deDoubleEnciphered, key1, "decipher") |
|||
return join({"Original text = " & originalText, ¬ |
|||
"Enciphered = " & enciphered, "Double enciphered = " & doubleEnciphered, ¬ |
|||
"De-double enciphered = " & deDoubleEnciphered, "Deciphered = " & deciphered}, linefeed) |
|||
end demo |
|||
demo("WELLDONEISBETTERTHANWELLSAID")</syntaxhighlight> |
|||
{{output}} |
|||
<syntaxhighlight lang="applescript">"Original text = WELLDONEISBETTERTHANWELLSAID |
|||
Enciphered = OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
Double enciphered = ZJVDGIXNNDNRHAXQUUJZGAFTANHW |
|||
De-double enciphered = OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
Deciphered = WELLDONEISBETTERTHANWELLSAID"</syntaxhighlight> |
|||
=={{header|Arc}}== |
=={{header|Arc}}== |
||
< |
<syntaxhighlight lang="arc">(= lshift '((0 1) (2 14) (1 2) (14 26))) |
||
(= rshift '((1 3) (4 15) (3 4) (15 26) (0 1))) |
(= rshift '((1 3) (4 15) (3 4) (15 26) (0 1))) |
||
Line 48: | Line 416: | ||
(chaocipher "HXUCZVAMDSLKPEFJRIGTWOBNYQ" "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
(chaocipher "HXUCZVAMDSLKPEFJRIGTWOBNYQ" "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
||
"OAHQHCNYNXTSZJRRHJBYHQKSOUJY" nil 1) |
"OAHQHCNYNXTSZJRRHJBYHQKSOUJY" nil 1) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{output}} |
{{output}} |
||
< |
<syntaxhighlight lang="arc"> |
||
arc> (chaocipher "HXUCZVAMDSLKPEFJRIGTWOBNYQ" "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
arc> (chaocipher "HXUCZVAMDSLKPEFJRIGTWOBNYQ" "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
||
"WELLDONEISBETTERTHANWELLSAID") |
"WELLDONEISBETTERTHANWELLSAID") |
||
Line 85: | Line 453: | ||
YFJBGMTKWNOQXCHIDVALZRSPUE JIBMESWKYZXUCOPRTLNHFAGVQD |
YFJBGMTKWNOQXCHIDVALZRSPUE JIBMESWKYZXUCOPRTLNHFAGVQD |
||
"OAHQHCNYNXTSZJRRHJBYHQKSOUJY" |
"OAHQHCNYNXTSZJRRHJBYHQKSOUJY" |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|AutoHotkey}}== |
|||
<syntaxhighlight lang="autohotkey">LeftW := "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
RghtW := "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
PlainText := "WELLDONEISBETTERTHANWELLSAID" |
|||
CipherText := Chao_Cipher(PlainText, LeftW, RghtW) ; "OAHQHCNYNXTSZJRRHJBYHQKSOUJY" |
|||
DecipherText:= Chao_Decipher(CipherText, LeftW, RghtW) ; "WELLDONEISBETTERTHANWELLSAID" |
|||
MsgBox % Result := "Original text:`t" PlainText "`nCipher text:`t" CipherText "`nDecipher text:`t" DecipherText |
|||
return |
|||
;------------------------------------------- |
|||
Chao_Cipher(PT, LeftW, RghtW){ |
|||
oRght:=StrSplit(RghtW), oLeft:=StrSplit(LeftW) |
|||
for i, p in StrSplit(PT){ |
|||
result .= (c := Key2Val(oRght, oLeft, p)) |
|||
oLeft:=Permute(oLeft, c, 1) |
|||
oRght:=Permute(oRght, p) |
|||
} |
|||
return result |
|||
} |
|||
;------------------------------------------- |
|||
Chao_Decipher(CT, LeftW, RghtW){ |
|||
oRght:=StrSplit(RghtW), oLeft:=StrSplit(LeftW) |
|||
for i, c in StrSplit(CT){ |
|||
result .= (p := Key2Val(oLeft, oRght, c)) |
|||
oLeft:=Permute(oLeft, c, 1) |
|||
oRght:=Permute(oRght, p) |
|||
} |
|||
return result |
|||
} |
|||
;------------------------------------------- |
|||
Key2Val(Key, Val, char){ |
|||
for i, ch in Key |
|||
if (ch = char) |
|||
return Val[i] |
|||
} |
|||
;------------------------------------------- |
|||
Permute(Arr, ch, dt:=0){ |
|||
for i, c in Arr |
|||
if (c=ch) |
|||
break |
|||
loop % i-dt |
|||
Arr.Push(Arr.RemoveAt(1)) ; shift left |
|||
ch := Arr[3-dt] ; save 2nd/3rd chr |
|||
loop % 11+dt |
|||
Arr[A_Index+2-dt]:=Arr[A_Index+3-dt] ; shift pos 3/4-14 left |
|||
Arr[14] := ch ; place 2nd/3rd chr in pos 14 |
|||
return Arr |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Original text: WELLDONEISBETTERTHANWELLSAID |
|||
Cipher text: OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
Decipher text: WELLDONEISBETTERTHANWELLSAID</pre> |
|||
=={{header|BASIC}}== |
|||
{{Works with|FreeBasic}} |
|||
{{Works with|PowerBasic}} |
|||
<SyntaxHighlight lang="BASIC"> |
|||
' Caocipher Example |
|||
' Rosetta Code |
|||
' This code was made in Power Basic 3.5 for DOS |
|||
CLS |
|||
' Left Alphabet |
|||
Function AlphaLeft(ct as String, pt as String, CharPos as Integer) as String |
|||
Dim tStr as String: tStr=ct |
|||
' 1. Shift the entire left alphabet cyclically so the ciphertext letter |
|||
' just enciphered is positioned at the zenith (i.e., position 1). |
|||
tStr=Right$(ct, Len(ct)-CharPos+1)+Left$(ct, CharPos-1) |
|||
' 2. Extract the letter found at position zenith+1 (i.e., the letter to |
|||
' the right of the zenith), taking it out of the alphabet, temporarily |
|||
' leaving an unfilled "hole" |
|||
Dim Hole as String: Hole=Mid$(tStr, 2, 1): Mid$(tStr, 2, 1)=" " |
|||
' 3. Shift all letters in positions zenith+2 up to, and including, the |
|||
' nadir (zenith+13), moving them one position to the left |
|||
tStr=Left$(tStr, 1)+Mid$(tStr, 3, 12)+" "+Right$(tStr, 12) |
|||
' 4. Insert the just-extracted letter into the nadir position |
|||
' (i.e., zenith+13) |
|||
Mid$(tStr, 14, 1)=Hole |
|||
AlphaLeft=tStr |
|||
End Function |
|||
' Right Alphabet |
|||
Function AlphaRight(ct as String, pt as String, CharPos as Integer) as String |
|||
Dim tStr as String: tStr=pt |
|||
' 1. Shift the entire right alphabet cyclically so the plaintext letter |
|||
' just enciphered is positioned at the zenith. |
|||
tStr=Right$(tStr, Len(tStr)-CharPos+1)+Left$(tStr, CharPos-1) |
|||
' 2. Now shift the entire alphabet one more position to the left (i.e., |
|||
' the leftmost letter moves cyclically to the far right), moving a new |
|||
' letter into the zenith position. |
|||
tStr=Right$(tStr, 25)+Left$(tStr, 1) |
|||
' 3. Extract the letter at position zenith+2, taking it out of the |
|||
' alphabet, temporarily leaving an unfilled "hole". |
|||
Dim Hole as String: Hole=Mid$(tStr, 3, 1): Mid$(tStr, 3, 1)=" ": |
|||
' 4. Shift all letters beginning with zenith+3 up to, and including, the |
|||
' nadir (zenith+13), moving them one position to the left. |
|||
tStr=Left$(tStr, 2)+Mid$(tStr, 4, 11)+" "+Right$(tStr, 12) |
|||
' 5. Insert the just-extracted letter into the nadir position (zenith+13) |
|||
Mid$(tStr, 14, 1)=Hole |
|||
AlphaRight=tStr |
|||
End Function |
|||
Function Encode(Text as String, ct as String, pt as String) as String |
|||
Dim t as Integer |
|||
Dim tStr as String: tStr="" |
|||
For t=1 to Len(Text) |
|||
Dim Char as String: Char=Mid$(Text, t, 1) |
|||
Dim CharPos as Integer: CharPos=Instr(pt, Char) |
|||
ct=AlphaLeft(ct, pt, CharPos) |
|||
pt=AlphaRight(ct, pt, CharPos) |
|||
tStr=tStr+Left$(ct, 1) |
|||
Next |
|||
Encode=tStr |
|||
End Function |
|||
' Deciphering a Chaocipher-encrypted message is identical to the steps used |
|||
' for enciphering. The sole difference is that the decipherer locates the |
|||
' known ciphertext letter in the left (ct) alphabet, with the plaintext |
|||
' letter being the corresponding letter in the right (pt) alphabet |
|||
' |
|||
' Alphabet permuting is identical in enciphering and deciphering |
|||
Function Decode(Text as String, ct as String, pt as String) as String |
|||
Dim t as Integer |
|||
Dim tStr as String: tStr="" |
|||
For t=1 to Len(Text) |
|||
Dim Char as String: Char=Mid$(Text, t, 1) |
|||
Dim CharPos as Integer: CharPos=Instr(ct, Char) |
|||
ct=AlphaLeft(ct, pt, CharPos) |
|||
pt=AlphaRight(ct, pt, CharPos) |
|||
tStr=tStr+Right$(pt, 1) |
|||
Next |
|||
Decode=tStr |
|||
End Function |
|||
' Start of Main Code |
|||
' LEFT (Cipher Text): HXUCZVAMDSLKPEFJRIGTWOBNYQ |
|||
Dim tLeft as String: tLeft="HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
' RIGHT (Plain Text): PTLNBQDEOYSFAVZKGJRIHWXUMC |
|||
Dim tRight as String: tRight="PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
' Cipher Message (Used to verify a good encoding) |
|||
Dim cText as String: cText="OAHQHCNYNXTSZJRRHJBYHQKSOUJY" |
|||
' Plain Text Message |
|||
Dim pText as String: pText="WELLDONEISBETTERTHANWELLSAID" |
|||
Print " Plain Text: "; pText: Print |
|||
Dim ctLeft as String: ctLeft=tLeft |
|||
Dim ptRight as String: ptRight=tRight |
|||
' Final Cipher Text |
|||
Dim eText as String: eText=Encode(pText, ctLeft, ptRight) |
|||
Print " Cipher Text: "; eText: Print |
|||
If eText=cText then Print "Successful" else Print "Failed" |
|||
ctLeft=tLeft: ptRight=tRight |
|||
Dim dText as String: dText=Decode(eText, ctLeft, ptRight) |
|||
Print: Print " Plain Text: "; dText: Print |
|||
If dText=pText then Print "Successful" else Print "Failed" |
|||
</SyntaxHighlight> |
|||
<pre> |
|||
Plain Text: WELLDONEISBETTERTHANWELLSAID |
|||
Cipher text: OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
Successful |
|||
Plain Text: WELLDONEISBETTERTHANWELLSAID |
|||
Successful |
|||
</pre> |
|||
=={{header|C}}== |
=={{header|C}}== |
||
{{trans|Kotlin}} |
{{trans|Kotlin}} |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <string.h> |
#include <string.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Line 160: | Line 730: | ||
free(plain_text2); |
free(plain_text2); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{output}} |
{{output}} |
||
Line 201: | Line 771: | ||
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID |
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID |
||
</pre> |
</pre> |
||
=={{header|C sharp|C#}}== |
|||
{{trans|D}} |
|||
<syntaxhighlight lang="csharp">using System; |
|||
namespace Chaocipher { |
|||
enum Mode { |
|||
ENCRYPT, |
|||
DECRYPT, |
|||
} |
|||
class Program { |
|||
const string L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"; |
|||
const string R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
|||
static string Exec(string text, Mode mode, bool showSteps = false) { |
|||
char[] left = L_ALPHABET.ToCharArray(); |
|||
char[] right = R_ALPHABET.ToCharArray(); |
|||
char[] eText = new char[text.Length]; |
|||
char[] temp = new char[26]; |
|||
for (int i = 0; i < text.Length; ++i) { |
|||
if (showSteps) Console.WriteLine("{0} {1}", string.Join("", left), string.Join("", right)); |
|||
int index = 0; |
|||
if (mode == Mode.ENCRYPT) { |
|||
index = Array.IndexOf(right, text[i]); |
|||
eText[i] = left[index]; |
|||
} else { |
|||
index = Array.IndexOf(left, text[i]); |
|||
eText[i] = right[index]; |
|||
} |
|||
if (i == text.Length - 1) break; |
|||
// permute left |
|||
for (int j = index; j < 26; ++j) temp[j - index] = left[j]; |
|||
for (int j = 0; j < index; ++j) temp[26 - index + j] = left[j]; |
|||
var store = temp[1]; |
|||
for (int j = 2; j < 14; ++j) temp[j - 1] = temp[j]; |
|||
temp[13] = store; |
|||
temp.CopyTo(left, 0); |
|||
// permute right |
|||
for (int j = index; j < 26; ++j) temp[j - index] = right[j]; |
|||
for (int j = 0; j < index; ++j) temp[26 - index + j] = right[j]; |
|||
store = temp[0]; |
|||
for (int j = 1; j < 26; ++j) temp[j - 1] = temp[j]; |
|||
temp[25] = store; |
|||
store = temp[2]; |
|||
for (int j = 3; j < 14; ++j) temp[j - 1] = temp[j]; |
|||
temp[13] = store; |
|||
temp.CopyTo(right, 0); |
|||
} |
|||
return new string(eText); |
|||
} |
|||
static void Main(string[] args) { |
|||
var plainText = "WELLDONEISBETTERTHANWELLSAID"; |
|||
Console.WriteLine("The original plaintext is : {0}", plainText); |
|||
Console.WriteLine("\nThe left and right alphabets after each permutation during encryption are :\n"); |
|||
var cipherText = Exec(plainText, Mode.ENCRYPT, true); |
|||
Console.WriteLine("\nThe ciphertext is : {0}", cipherText); |
|||
var plainText2 = Exec(cipherText, Mode.DECRYPT); |
|||
Console.WriteLine("\nThe recovered plaintext is : {0}", plainText2); |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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</pre> |
|||
=={{header|C++}}== |
=={{header|C++}}== |
||
{{trans|C#}} |
{{trans|C#}} |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
enum class Mode { |
enum class Mode { |
||
Line 270: | Line 944: | ||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>The original plaintext is : WELLDONEISBETTERTHANWELLSAID |
<pre>The original plaintext is : WELLDONEISBETTERTHANWELLSAID |
||
Line 307: | Line 981: | ||
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID</pre> |
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID</pre> |
||
=={{header|C#|C sharp}}== |
|||
{{trans|D}} |
|||
<lang csharp>using System; |
|||
namespace Chaocipher { |
|||
enum Mode { |
|||
ENCRYPT, |
|||
DECRYPT, |
|||
} |
|||
class Program { |
|||
const string L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"; |
|||
const string R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
|||
static string Exec(string text, Mode mode, bool showSteps = false) { |
|||
char[] left = L_ALPHABET.ToCharArray(); |
|||
char[] right = R_ALPHABET.ToCharArray(); |
|||
char[] eText = new char[text.Length]; |
|||
char[] temp = new char[26]; |
|||
for (int i = 0; i < text.Length; ++i) { |
|||
if (showSteps) Console.WriteLine("{0} {1}", string.Join("", left), string.Join("", right)); |
|||
int index = 0; |
|||
if (mode == Mode.ENCRYPT) { |
|||
index = Array.IndexOf(right, text[i]); |
|||
eText[i] = left[index]; |
|||
} else { |
|||
index = Array.IndexOf(left, text[i]); |
|||
eText[i] = right[index]; |
|||
} |
|||
if (i == text.Length - 1) break; |
|||
// permute left |
|||
for (int j = index; j < 26; ++j) temp[j - index] = left[j]; |
|||
for (int j = 0; j < index; ++j) temp[26 - index + j] = left[j]; |
|||
var store = temp[1]; |
|||
for (int j = 2; j < 14; ++j) temp[j - 1] = temp[j]; |
|||
temp[13] = store; |
|||
temp.CopyTo(left, 0); |
|||
// permute right |
|||
for (int j = index; j < 26; ++j) temp[j - index] = right[j]; |
|||
for (int j = 0; j < index; ++j) temp[26 - index + j] = right[j]; |
|||
store = temp[0]; |
|||
for (int j = 1; j < 26; ++j) temp[j - 1] = temp[j]; |
|||
temp[25] = store; |
|||
store = temp[2]; |
|||
for (int j = 3; j < 14; ++j) temp[j - 1] = temp[j]; |
|||
temp[13] = store; |
|||
temp.CopyTo(right, 0); |
|||
} |
|||
return new string(eText); |
|||
} |
|||
static void Main(string[] args) { |
|||
var plainText = "WELLDONEISBETTERTHANWELLSAID"; |
|||
Console.WriteLine("The original plaintext is : {0}", plainText); |
|||
Console.WriteLine("\nThe left and right alphabets after each permutation during encryption are :\n"); |
|||
var cipherText = Exec(plainText, Mode.ENCRYPT, true); |
|||
Console.WriteLine("\nThe ciphertext is : {0}", cipherText); |
|||
var plainText2 = Exec(cipherText, Mode.DECRYPT); |
|||
Console.WriteLine("\nThe recovered plaintext is : {0}", plainText2); |
|||
} |
|||
} |
|||
}</lang> |
|||
{{out}} |
|||
<pre>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</pre> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
{{trans|Kotlin}} |
{{trans|Kotlin}} |
||
< |
<syntaxhighlight lang="d">import std.stdio; |
||
import std.string; |
import std.string; |
||
Line 479: | Line 1,046: | ||
auto plainText2 = exec(cipherText, Mode.DECRYPT); |
auto plainText2 = exec(cipherText, Mode.DECRYPT); |
||
writeln("\nThe recovered plaintext is : ", plainText2); |
writeln("\nThe recovered plaintext is : ", plainText2); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>The original plaintext is : WELLDONEISBETTERTHANWELLSAID |
<pre>The original plaintext is : WELLDONEISBETTERTHANWELLSAID |
||
Line 517: | Line 1,084: | ||
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID</pre> |
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID</pre> |
||
=={{header|Delphi}}== |
|||
{{libheader| System.SysUtils}} |
|||
{{Trans|Kotlin}} |
|||
<syntaxhighlight lang="delphi"> |
|||
program Chaocipher; |
|||
{$APPTYPE CONSOLE} |
|||
uses |
|||
System.SysUtils; |
|||
type |
|||
TMode = (mcEncrypt, mcDecrypt); |
|||
const |
|||
lAlphabet = 'HXUCZVAMDSLKPEFJRIGTWOBNYQ'; |
|||
rAlphabet = 'PTLNBQDEOYSFAVZKGJRIHWXUMC'; |
|||
function Chao(text: AnsiString; Mode: TMode; showSteps: boolean): AnsiString; |
|||
begin |
|||
var len := Length(text); |
|||
var left: AnsiString := lAlphabet; |
|||
var right: AnsiString := rAlphabet; |
|||
var eText: AnsiString; |
|||
SetLength(eText, len); |
|||
var temp: AnsiString; |
|||
SetLength(temp, 26); |
|||
for var i := 0 to len - 1 do |
|||
begin |
|||
if showSteps then |
|||
writeln(left, ' ', right); |
|||
var index := 0; |
|||
if Mode = mcEncrypt then |
|||
begin |
|||
index := pos(text[i + 1], right) - 1; |
|||
eText[i + 1] := left[index + 1]; |
|||
end |
|||
else |
|||
begin |
|||
index := pos(text[i + 1], left) - 1; |
|||
eText[i + 1] := right[index + 1]; |
|||
end; |
|||
if i = len - 1 then |
|||
Break; |
|||
// premute left |
|||
for var j := index to 25 do |
|||
temp[j - index + 1] := left[j + 1]; |
|||
for var j := 0 to index - 1 do |
|||
temp[27 - index + j] := left[j + 1]; |
|||
var store := temp[2]; |
|||
for var j := 2 to 13 do |
|||
temp[j] := temp[j + 1]; |
|||
temp[14] := store; |
|||
left := temp; |
|||
// permute right |
|||
for var j := index to 25 do |
|||
temp[j - index + 1] := right[j + 1]; |
|||
for var j := 0 to index - 1 do |
|||
temp[27 - index + j] := right[j + 1]; |
|||
store := temp[0 + 1]; |
|||
for var j := 1 to 25 do |
|||
temp[j] := temp[j + 1]; |
|||
temp[26] := store; |
|||
store := temp[3]; |
|||
for var j := 3 to 13 do |
|||
temp[j] := temp[j + 1]; |
|||
temp[14] := store; |
|||
right := temp; |
|||
end; |
|||
Result := eText; |
|||
end; |
|||
begin |
|||
var plainText := 'WELLDONEISBETTERTHANWELLSAID'; |
|||
writeln('The original plaintext is :', plainText); |
|||
write(#10'The left and right alphabets after each permutation '); |
|||
writeln('during encryption are :'#10); |
|||
var cipherText := Chao(plainText, mcEncrypt, true); |
|||
writeln(#10'The ciphertext is :', cipherText); |
|||
var plainText2 := Chao(cipherText, mcDecrypt, false); |
|||
writeln(#10'The recovered plaintext is : ', plainText2); |
|||
readln; |
|||
end.</syntaxhighlight> |
|||
=={{header|EasyLang}}== |
|||
<syntaxhighlight> |
|||
proc index c$ . a$[] ind . |
|||
for ind = 1 to len a$[] |
|||
if a$[ind] = c$ |
|||
return |
|||
. |
|||
. |
|||
ind = 0 |
|||
. |
|||
left$ = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
right$ = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
# |
|||
func$ chao txt$ mode . |
|||
left$[] = strchars left$ |
|||
right$[] = strchars right$ |
|||
len tmp$[] 26 |
|||
for c$ in strchars txt$ |
|||
# print strjoin left$[] & " " & strjoin right$[] |
|||
if mode = 1 |
|||
index c$ right$[] ind |
|||
if ind = 0 |
|||
return "" |
|||
. |
|||
r$ &= left$[ind] |
|||
else |
|||
index c$ left$[] ind |
|||
if ind = 0 |
|||
print c$ |
|||
return "" |
|||
. |
|||
r$ &= right$[ind] |
|||
. |
|||
# permute left |
|||
for j = ind to 26 |
|||
tmp$[j - ind + 1] = left$[j] |
|||
. |
|||
for j = 1 to ind - 1 |
|||
tmp$[26 - ind + j + 1] = left$[j] |
|||
. |
|||
h$ = tmp$[2] |
|||
for j = 3 to 14 |
|||
tmp$[j - 1] = tmp$[j] |
|||
. |
|||
tmp$[14] = h$ |
|||
swap tmp$[] left$[] |
|||
# |
|||
# permute right |
|||
for j = ind to 26 |
|||
tmp$[j - ind + 1] = right$[j] |
|||
. |
|||
for j = 1 to ind - 1 |
|||
tmp$[26 - ind + j + 1] = right$[j] |
|||
. |
|||
h$ = tmp$[1] |
|||
for j = 2 to 26 |
|||
tmp$[j - 1] = tmp$[j] |
|||
. |
|||
tmp$[26] = h$ |
|||
h$ = tmp$[3] |
|||
for j = 4 to 14 |
|||
tmp$[j - 1] = tmp$[j] |
|||
. |
|||
tmp$[14] = h$ |
|||
swap tmp$[] right$[] |
|||
. |
|||
return r$ |
|||
. |
|||
h$ = chao "WELLDONEISBETTERTHANWELLSAID" 1 |
|||
print h$ |
|||
print chao h$ 2 |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
WELLDONEISBETTERTHANWELLSAID |
|||
</pre> |
|||
=={{header|EMal}}== |
|||
{{trans|C#}} |
|||
<syntaxhighlight lang="emal"> |
|||
type Chaocipher:Mode |
|||
enum |
|||
int ENCRYPT, DECRYPT |
|||
end |
|||
type Chaocipher |
|||
text L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
text R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
fun exec = text by text value, Chaocipher:Mode mode, logic showSteps |
|||
^|since texts are mutable, we can operate directly on them without the need of Lists|^ |
|||
text left = *L_ALPHABET # by using the valueOf operator we are sure that the string is copied |
|||
text right = *R_ALPHABET |
|||
text eText = text(" ", value.length) |
|||
text temp = text(" ", 26) |
|||
for int i = 0; i < value.length; ++i |
|||
if showSteps do writeLine(left + " " + right) end |
|||
int index = 0 |
|||
if mode == Chaocipher:Mode.ENCRYPT |
|||
index = right.find(value[i]) |
|||
eText[i] = left[index] |
|||
else |
|||
index = left.find(value[i]) |
|||
eText[i] = right[index] |
|||
end |
|||
if i == value.length - 1 do break end |
|||
# permute left |
|||
for int j = index; j < 26; ++j do temp[j - index] = left[j] end |
|||
for int j = 0; j < index; ++j do temp[26 - index + j] = left[j] end |
|||
var store = temp[1] |
|||
for int j = 2; j < 14; ++j do temp[j - 1] = temp[j] end |
|||
temp[13] = store |
|||
left = *temp |
|||
# permute right |
|||
for int j = index; j < 26; ++j do temp[j - index] = right[j] end |
|||
for int j = 0; j < index; ++j do temp[26 - index + j] = right[j] end |
|||
store = temp[0] |
|||
for int j = 1; j < 26; ++j do temp[j - 1] = temp[j] end |
|||
temp[25] = store |
|||
store = temp[2] |
|||
for int j = 3; j < 14; ++j do temp[j - 1] = temp[j] end |
|||
temp[13] = store |
|||
right = *temp |
|||
end |
|||
return eText |
|||
end |
|||
var plainText = "WELLDONEISBETTERTHANWELLSAID" |
|||
writeLine("The original plaintext is : " + plainText) |
|||
writeLine(EOL + "The left and right alphabets after each permutation during encryption are :" + EOL) |
|||
var cipherText = exec(plainText, Chaocipher:Mode.ENCRYPT, true) |
|||
writeLine(EOL + "The ciphertext is : " + cipherText) |
|||
var plainText2 = exec(cipherText, Chaocipher:Mode.DECRYPT, false) |
|||
writeLine(EOL + "The recovered plaintext is : " + plainText2) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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 |
|||
</pre> |
|||
=={{header|F_Sharp|F#}}== |
=={{header|F_Sharp|F#}}== |
||
===The Functions=== |
===The Functions=== |
||
< |
<syntaxhighlight lang="fsharp"> |
||
// Implement Chaocipher. Nigel Galloway: July 13th., 2019 |
// Implement Chaocipher. Nigel Galloway: July 13th., 2019 |
||
let pL n=function g when g=n->0 |g when g=(n+1)%26->13 |g->let x=(25+g-n)%26 in if x<13 then x else x+1 |
let pL n=function g when g=n->0 |g when g=(n+1)%26->13 |g->let x=(25+g-n)%26 in if x<13 then x else x+1 |
||
Line 528: | Line 1,370: | ||
let decrypt lW rW txt=Array.scan(fun (_,lW,rW) t->let n=Array.findIndex(fun n->n=t) lW in ((Array.item n rW,Array.permute(pL n) lW,(Array.permute(pR n) rW))))('0',lW,rW) txt |
let decrypt lW rW txt=Array.scan(fun (_,lW,rW) t->let n=Array.findIndex(fun n->n=t) lW in ((Array.item n rW,Array.permute(pL n) lW,(Array.permute(pR n) rW))))('0',lW,rW) txt |
||
|>Array.skip 1|>Array.map(fun(n,_,_)->n)|>System.String |
|>Array.skip 1|>Array.map(fun(n,_,_)->n)|>System.String |
||
</syntaxhighlight> |
|||
</lang> |
|||
===The Task=== |
===The Task=== |
||
< |
<syntaxhighlight lang="fsharp"> |
||
printfn "%s" (encrypt ("HXUCZVAMDSLKPEFJRIGTWOBNYQ".ToCharArray()) ("PTLNBQDEOYSFAVZKGJRIHWXUMC".ToCharArray()) ("WELLDONEISBETTERTHANWELLSAID".ToCharArray())) |
printfn "%s" (encrypt ("HXUCZVAMDSLKPEFJRIGTWOBNYQ".ToCharArray()) ("PTLNBQDEOYSFAVZKGJRIHWXUMC".ToCharArray()) ("WELLDONEISBETTERTHANWELLSAID".ToCharArray())) |
||
printfn "%s" (decrypt ("HXUCZVAMDSLKPEFJRIGTWOBNYQ".ToCharArray()) ("PTLNBQDEOYSFAVZKGJRIHWXUMC".ToCharArray()) ("OAHQHCNYNXTSZJRRHJBYHQKSOUJY".ToCharArray())) |
printfn "%s" (decrypt ("HXUCZVAMDSLKPEFJRIGTWOBNYQ".ToCharArray()) ("PTLNBQDEOYSFAVZKGJRIHWXUMC".ToCharArray()) ("OAHQHCNYNXTSZJRRHJBYHQKSOUJY".ToCharArray())) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 540: | Line 1,382: | ||
WELLDONEISBETTERTHANWELLSAID |
WELLDONEISBETTERTHANWELLSAID |
||
</pre> |
</pre> |
||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
< |
<syntaxhighlight lang="factor">USING: arrays combinators fry io kernel locals math namespaces |
||
prettyprint sequences sequences.extras strings ; |
prettyprint sequences sequences.extras strings ; |
||
IN: rosetta-code.chaocipher |
IN: rosetta-code.chaocipher |
||
Line 602: | Line 1,443: | ||
[ print ] bi@ ; |
[ print ] bi@ ; |
||
MAIN: main</ |
MAIN: main</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 608: | Line 1,449: | ||
WELLDONEISBETTERTHANWELLSAID |
WELLDONEISBETTERTHANWELLSAID |
||
</pre> |
</pre> |
||
=={{header|Fōrmulæ}}== |
=={{header|Fōrmulæ}}== |
||
{{FormulaeEntry|page=https://formulae.org/?script=examples/Chaocipher}} |
|||
'''Solution''' |
|||
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text ([http://wiki.formulae.org/Editing_F%C5%8Drmul%C3%A6_expressions more info]). Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for transportation effects more than visualization and edition. |
|||
[[File:Fōrmulæ - Chaocipher 01.png]] |
|||
'''Test 1.''' Encryption |
|||
[[File:Fōrmulæ - Chaocipher 02.png]] |
|||
[[File:Fōrmulæ - Chaocipher 03.png]] |
|||
'''Test 2.''' Decryption |
|||
[[File:Fōrmulæ - Chaocipher 04.png]] |
|||
[[File:Fōrmulæ - Chaocipher 05.png]] |
|||
=={{header|FreeBASIC}}== |
|||
The [[#BASIC|BASIC]] solution works without any changes. |
|||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="FutureBasic"> |
|||
begin enum |
|||
_encrypt |
|||
_decrypt |
|||
end enum |
|||
local fn chaocipher(orig as str255, action as byte, show as bool) as str255 |
|||
str255 leftStr, rightStr, out |
|||
short i, index |
|||
leftStr = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
rightStr = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
orig = ucase$(orig) |
|||
out[0] = orig[0] |
|||
if show then print:print,"The left and right alphabets during encryption are:":print |
|||
for i = 1 to orig[0] |
|||
if show then print ,leftStr,,rightStr |
|||
if action == _encrypt |
|||
index = instr$(0, rightStr, mid$(orig, i, 1)) |
|||
out[i] = leftStr[index] |
|||
else |
|||
index = instr$(0, leftStr, mid$(orig, i, 1)) |
|||
out[i] = rightStr[index] |
|||
end if |
|||
//leftStr permutation |
|||
leftStr = mid$(leftStr, index) + left$(leftStr, index-1) |
|||
leftStr = left$(leftStr, 1) + mid$(leftStr, 3, 12) + mid$(leftStr, 2, 1) + mid$(leftStr, 15) |
|||
//rightStr permutation |
|||
rightStr = mid$(rightStr, index+1) + left$(rightStr, index-1) + mid$(rightStr, index, 1) |
|||
rightStr = left$(rightStr, 2) + mid$(rightStr, 4, 11) + mid$(rightStr, 3, 1) + mid$(rightStr, 15) |
|||
next |
|||
end fn = out |
|||
str255 original, encrypted, decrypted |
|||
original = "WellDoneIsBetterThanWellSaid" |
|||
window 1, @"Chaocipher", ( 0, 0, 475, 550 ) |
|||
print : print ,"The original text is: """; original; """" |
|||
encrypted = fn chaocipher(original, _encrypt, yes) |
|||
print : print ,"The encrypted text is: """; encrypted; """" |
|||
decrypted = fn chaocipher(encrypted, _decrypt, no) |
|||
print : print ,"The decrypted text is: """; decrypted; """" |
|||
handleevents |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
[[File:FB Chaocipher results.png]] |
|||
The option to show Fōrmulæ programs and their results is showing images. Unfortunately images cannot be uploaded in Rosetta Code. |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
{{trans|Kotlin}} |
{{trans|Kotlin}} |
||
< |
<syntaxhighlight lang="go">package main |
||
import( |
import( |
||
Line 713: | Line 1,624: | ||
plainText2 := Chao(cipherText, Decrypt, false) |
plainText2 := Chao(cipherText, Decrypt, false) |
||
fmt.Println("\nThe recovered plaintext is :", plainText2) |
fmt.Println("\nThe recovered plaintext is :", plainText2) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 720: | Line 1,631: | ||
</pre> |
</pre> |
||
=={{header|Groovy}}== |
|||
{{trans|Java}} |
|||
<syntaxhighlight lang="groovy">class Chaocipher { |
|||
private enum Mode { |
|||
ENCRYPT, |
|||
DECRYPT |
|||
} |
|||
private static final String L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
private static final String R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
private static int indexOf(char[] a, char c) { |
|||
for (int i = 0; i < a.length; ++i) { |
|||
if (a[i] == c) { |
|||
return i |
|||
} |
|||
} |
|||
return -1 |
|||
} |
|||
private static String exec(String text, Mode mode) { |
|||
return exec(text, mode, false) |
|||
} |
|||
private static String exec(String text, Mode mode, Boolean showSteps) { |
|||
char[] left = L_ALPHABET.toCharArray() |
|||
char[] right = R_ALPHABET.toCharArray() |
|||
char[] eText = new char[text.length()] |
|||
char[] temp = new char[26] |
|||
for (int i = 0; i < text.length(); ++i) { |
|||
if (showSteps) { |
|||
println("${new String(left)} ${new String(right)}") |
|||
} |
|||
int index |
|||
if (mode == Mode.ENCRYPT) { |
|||
index = indexOf(right, text.charAt(i)) |
|||
eText[i] = left[index] |
|||
} else { |
|||
index = indexOf(left, text.charAt(i)) |
|||
eText[i] = right[index] |
|||
} |
|||
if (i == text.length() - 1) { |
|||
break |
|||
} |
|||
// permute left |
|||
if (26 - index >= 0) System.arraycopy(left, index, temp, 0, 26 - index) |
|||
System.arraycopy(left, 0, temp, 26 - index, index) |
|||
char store = temp[1] |
|||
System.arraycopy(temp, 2, temp, 1, 12) |
|||
temp[13] = store |
|||
left = Arrays.copyOf(temp, temp.length) |
|||
// permute right |
|||
if (26 - index >= 0) System.arraycopy(right, index, temp, 0, 26 - index) |
|||
System.arraycopy(right, 0, temp, 26 - index, index) |
|||
store = temp[0] |
|||
System.arraycopy(temp, 1, temp, 0, 25) |
|||
temp[25] = store |
|||
store = temp[2] |
|||
System.arraycopy(temp, 3, temp, 2, 11) |
|||
temp[13] = store |
|||
right = Arrays.copyOf(temp, temp.length) |
|||
} |
|||
return new String(eText) |
|||
} |
|||
static void main(String[] args) { |
|||
String plainText = "WELLDONEISBETTERTHANWELLSAID" |
|||
println("The original plaintext is : $plainText") |
|||
println("\nThe left and right alphabets after each permutation during encryption are:") |
|||
String cipherText = exec(plainText, Mode.ENCRYPT, true) |
|||
println("\nThe cipher text is : $cipherText") |
|||
String plainText2 = exec(cipherText, Mode.DECRYPT) |
|||
println("\nThe recovered plaintext is : $plainText2") |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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 cipher text is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID</pre> |
|||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
< |
<syntaxhighlight lang="haskell">import Data.List (elemIndex) |
||
chao :: Eq a => [a] -> [a] -> Bool -> [a] -> [a] |
chao :: Eq a => [a] -> [a] -> Bool -> [a] -> [a] |
||
chao _ _ _ [] = [] |
chao _ _ _ [] = [] |
||
chao l r plain (x:xs) = maybe [] go (elemIndex x src) |
chao l r plain (x : xs) = maybe [] go (elemIndex x src) |
||
where |
where |
||
(src, dst) |
(src, dst) |
||
Line 739: | Line 1,767: | ||
rotated :: Int -> [a] -> [a] |
rotated :: Int -> [a] -> [a] |
||
rotated |
rotated n = take . length <*> drop n . cycle |
||
shifted :: Int -> Int -> [a] -> [a] |
shifted :: Int -> Int -> [a] -> [a] |
||
shifted src dst s = |
shifted src dst s = concat [x, rotated 1 y, b] |
||
where |
|||
let (a, b) = splitAt dst s |
|||
(a, b) = splitAt dst s |
|||
(x, y) = splitAt src a |
|||
encode, decode :: Bool |
|||
encode = False |
encode = False |
||
decode = True |
decode = True |
||
Line 754: | Line 1,782: | ||
main = do |
main = do |
||
let chaoWheels = |
let chaoWheels = |
||
chao |
|||
chao "HXUCZVAMDSLKPEFJRIGTWOBNYQ" "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
"HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
"PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
plainText = "WELLDONEISBETTERTHANWELLSAID" |
plainText = "WELLDONEISBETTERTHANWELLSAID" |
||
cipherText = chaoWheels encode plainText |
cipherText = chaoWheels encode plainText |
||
mapM_ |
|||
print plainText |
|||
print |
|||
print cipherText |
|||
[ plainText, |
|||
print $ chaoWheels decode cipherText</lang> |
|||
cipherText, |
|||
chaoWheels decode cipherText |
|||
]</syntaxhighlight> |
|||
{{Out}} |
{{Out}} |
||
<pre> |
<pre> |
||
Line 766: | Line 1,799: | ||
"WELLDONEISBETTERTHANWELLSAID"</pre> |
"WELLDONEISBETTERTHANWELLSAID"</pre> |
||
=={{header|J}}== |
|||
{{trans|Raku}} |
|||
<syntaxhighlight lang="j">reset =: verb define |
|||
LEFT =: 'HXUCZVAMDSLKPEFJRIGTWOBNYQ' |
|||
RIGHT =: 'PTLNBQDEOYSFAVZKGJRIHWXUMC' |
|||
) |
|||
enc =: verb define |
|||
z =. LEFT {~ i =. RIGHT i. y |
|||
permute {. i |
|||
z |
|||
) |
|||
dec =: verb define |
|||
z =. RIGHT {~ i =. LEFT i. y |
|||
permute {. i |
|||
z |
|||
) |
|||
permute =: verb define |
|||
LEFT =: LEFT |.~ - y |
|||
LEFT =: (1 |. 13 {. LEFT) , 13 }. LEFT |
|||
RIGHT =: RIGHT |.~ - y + 1 |
|||
RIGHT =: ({. RIGHT) , (1 |. RIGHT {~ 2+i.12) , 13 }. RIGHT |
|||
) |
|||
chao =: enc :. dec |
|||
reset '' |
|||
smoutput E =. chao 'WELLDONEISBETTERTHANWELLSAID' |
|||
reset '' |
|||
smoutput D =. chao^:_1 E</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
OMUUADCMTLZMXXMGXWPCOMUULPTA |
|||
WELLDONEISBETTERTHANWELLSAID |
|||
</pre> |
|||
=={{header|Java}}== |
|||
{{trans|Kotlin}} |
|||
<syntaxhighlight lang="java">import java.util.Arrays; |
|||
public class Chaocipher { |
|||
private enum Mode { |
|||
ENCRYPT, |
|||
DECRYPT |
|||
} |
|||
private static final String L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"; |
|||
private static final String R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
|||
private static int indexOf(char[] a, char c) { |
|||
for (int i = 0; i < a.length; ++i) { |
|||
if (a[i] == c) { |
|||
return i; |
|||
} |
|||
} |
|||
return -1; |
|||
} |
|||
private static String exec(String text, Mode mode) { |
|||
return exec(text, mode, false); |
|||
} |
|||
private static String exec(String text, Mode mode, Boolean showSteps) { |
|||
char[] left = L_ALPHABET.toCharArray(); |
|||
char[] right = R_ALPHABET.toCharArray(); |
|||
char[] eText = new char[text.length()]; |
|||
char[] temp = new char[26]; |
|||
for (int i = 0; i < text.length(); ++i) { |
|||
if (showSteps) { |
|||
System.out.printf("%s %s\n", new String(left), new String(right)); |
|||
} |
|||
int index; |
|||
if (mode == Mode.ENCRYPT) { |
|||
index = indexOf(right, text.charAt(i)); |
|||
eText[i] = left[index]; |
|||
} else { |
|||
index = indexOf(left, text.charAt(i)); |
|||
eText[i] = right[index]; |
|||
} |
|||
if (i == text.length() - 1) { |
|||
break; |
|||
} |
|||
// permute left |
|||
if (26 - index >= 0) System.arraycopy(left, index, temp, 0, 26 - index); |
|||
System.arraycopy(left, 0, temp, 26 - index, index); |
|||
char store = temp[1]; |
|||
System.arraycopy(temp, 2, temp, 1, 12); |
|||
temp[13] = store; |
|||
left = Arrays.copyOf(temp, temp.length); |
|||
// permute right |
|||
if (26 - index >= 0) System.arraycopy(right, index, temp, 0, 26 - index); |
|||
System.arraycopy(right, 0, temp, 26 - index, index); |
|||
store = temp[0]; |
|||
System.arraycopy(temp, 1, temp, 0, 25); |
|||
temp[25] = store; |
|||
store = temp[2]; |
|||
System.arraycopy(temp, 3, temp, 2, 11); |
|||
temp[13] = store; |
|||
right = Arrays.copyOf(temp, temp.length); |
|||
} |
|||
return new String(eText); |
|||
} |
|||
public static void main(String[] args) { |
|||
String plainText = "WELLDONEISBETTERTHANWELLSAID"; |
|||
System.out.printf("The original plaintext is : %s\n", plainText); |
|||
System.out.println("\nThe left and right alphabets after each permutation during encryption are:"); |
|||
String cipherText = exec(plainText, Mode.ENCRYPT, true); |
|||
System.out.printf("\nThe cipher text is : %s\n", cipherText); |
|||
String plainText2 = exec(cipherText, Mode.DECRYPT); |
|||
System.out.printf("\nThe recovered plaintext is : %s\n", plainText2); |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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 cipher text is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID</pre> |
|||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
{{trans|C}} |
{{trans|C}} |
||
Script source |
Script source |
||
< |
<syntaxhighlight lang="javascript">const L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"; |
||
const R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
const R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
||
Line 868: | Line 2,059: | ||
var decipher_text = chao(cipher_text, DECRYPT, false); |
var decipher_text = chao(cipher_text, DECRYPT, false); |
||
out.innerHTML += "<p>The recovered plaintext is : " + decipher_text + "</p>"; |
out.innerHTML += "<p>The recovered plaintext is : " + decipher_text + "</p>"; |
||
}</ |
}</syntaxhighlight> |
||
Solution page |
Solution page |
||
< |
<syntaxhighlight lang="html"><!DOCTYPE html> |
||
<html> |
<html> |
||
<head> |
<head> |
||
Line 880: | Line 2,071: | ||
<div id="content"></div> |
<div id="content"></div> |
||
</body> |
</body> |
||
</html></ |
</html></syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>The original plaintext is : WELLDONEISBETTERTHANWELLSAID |
<pre>The original plaintext is : WELLDONEISBETTERTHANWELLSAID |
||
The ciphertext is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
The ciphertext is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
||
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID</pre> |
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID</pre> |
||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
Modified from the Kotlin and |
Modified from the Kotlin and Raku entries. |
||
< |
<syntaxhighlight lang="julia">const leftalphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
||
const rightalphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
const rightalphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
||
Line 918: | Line 2,108: | ||
testchacocipher("WELLDONEISBETTERTHANWELLSAID") |
testchacocipher("WELLDONEISBETTERTHANWELLSAID") |
||
</ |
</syntaxhighlight>{{out}} |
||
<pre> |
<pre> |
||
The original plaintext is: WELLDONEISBETTERTHANWELLSAID |
The original plaintext is: WELLDONEISBETTERTHANWELLSAID |
||
Line 956: | Line 2,146: | ||
Decoded, the recovered plaintext is: WELLDONEISBETTERTHANWELLSAID |
Decoded, the recovered plaintext is: WELLDONEISBETTERTHANWELLSAID |
||
</pre> |
</pre> |
||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
This is based on the C# implementation referred to in the task description, except that the encrypt and decrypt operations are combined into a single method. |
This is based on the C# implementation referred to in the task description, except that the encrypt and decrypt operations are combined into a single method. |
||
< |
<syntaxhighlight lang="scala">// Version 1.2.40 |
||
enum class Mode { ENCRYPT, DECRYPT } |
enum class Mode { ENCRYPT, DECRYPT } |
||
Line 1,021: | Line 2,210: | ||
val plainText2 = Chao.exec(cipherText, Mode.DECRYPT) |
val plainText2 = Chao.exec(cipherText, Mode.DECRYPT) |
||
println("\nThe recovered plaintext is : $plainText2") |
println("\nThe recovered plaintext is : $plainText2") |
||
}</ |
}</syntaxhighlight> |
||
{{output}} |
{{output}} |
||
Line 1,062: | Line 2,251: | ||
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID |
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID |
||
</pre> |
</pre> |
||
=={{header|Lua}}== |
|||
<syntaxhighlight lang="lua">-- Chaocipher, in Lua, 6/19/2020 db |
|||
local Chaocipher = { |
|||
ct = "HXUCZVAMDSLKPEFJRIGTWOBNYQ", |
|||
pt = "PTLNBQDEOYSFAVZKGJRIHWXUMC", |
|||
encrypt = function(self, text) return self:_encdec(text, true) end, |
|||
decrypt = function(self, text) return self:_encdec(text, false) end, |
|||
_encdec = function(self, text, encflag) |
|||
local ct, pt, s = self.ct, self.pt, "" |
|||
local cshl = function(s,i) return s:sub(i) .. s:sub(1,i-1) end |
|||
local sshl = function(s,i) return s:sub(1,i-1) .. s:sub(i+1,14) .. s:sub(i,i) .. s:sub(15) end |
|||
for ch in text:gmatch(".") do |
|||
local i = (encflag and pt or ct):find(ch) |
|||
s = s .. (encflag and ct or pt):sub(i,i) |
|||
if encflag then print(ct, pt, ct:sub(i,i), pt:sub(i,i)) end |
|||
ct, pt = sshl(cshl(ct, i), 2), sshl(cshl(pt, i+1), 3) |
|||
end |
|||
return s |
|||
end, |
|||
} |
|||
local plainText = "WELLDONEISBETTERTHANWELLSAID" |
|||
local encryptText = Chaocipher:encrypt(plainText) |
|||
local decryptText = Chaocipher:decrypt(encryptText) |
|||
print() |
|||
print("The original text was: " .. plainText) |
|||
print("The encrypted text is: " .. encryptText) |
|||
print("The decrypted text is: " .. decryptText)</syntaxhighlight> |
|||
{{out}} |
|||
<pre>HXUCZVAMDSLKPEFJRIGTWOBNYQ PTLNBQDEOYSFAVZKGJRIHWXUMC O W |
|||
ONYQHXUCZVAMDBSLKPEFJRIGTW XUCPTLNBQDEOYMSFAVZKGJRIHW A E |
|||
ADBSLKPEFJRIGMTWONYQHXUCZV OYSFAVZKGJRIHMWXUCPTLNBQDE H L |
|||
HUCZVADBSLKPEXFJRIGMTWONYQ NBDEOYSFAVZKGQJRIHMWXUCPTL Q L |
|||
QUCZVADBSLKPEHXFJRIGMTWONY NBEOYSFAVZKGQDJRIHMWXUCPTL H D |
|||
HFJRIGMTWONYQXUCZVADBSLKPE JRHMWXUCPTLNBIEOYSFAVZKGQD C O |
|||
CVADBSLKPEHFJZRIGMTWONYQXU YSAVZKGQDJRHMFWXUCPTLNBIEO N N |
|||
NQXUCVADBSLKPYEHFJZRIGMTWO BIOYSAVZKGQDJERHMFWXUCPTLN Y E |
|||
YHFJZRIGMTWONEQXUCVADBSLKP RHFWXUCPTLNBIMOYSAVZKGQDJE N I |
|||
NQXUCVADBSLKPEYHFJZRIGMTWO MOSAVZKGQDJERYHFWXUCPTLNBI X S |
|||
XCVADBSLKPEYHUFJZRIGMTWONQ AVKGQDJERYHFWZXUCPTLNBIMOS T B |
|||
TONQXCVADBSLKWPEYHUFJZRIGM IMSAVKGQDJERYOHFWZXUCPTLNB S E |
|||
SKWPEYHUFJZRILGMTONQXCVADB RYHFWZXUCPTLNOBIMSAVKGQDJE Z T |
|||
ZILGMTONQXCVARDBSKWPEYHUFJ LNBIMSAVKGQDJOERYHFWZXUCPT J T |
|||
JILGMTONQXCVAZRDBSKWPEYHUF LNIMSAVKGQDJOBERYHFWZXUCPT R E |
|||
RBSKWPEYHUFJIDLGMTONQXCVAZ RYFWZXUCPTLNIHMSAVKGQDJOBE R R |
|||
RSKWPEYHUFJIDBLGMTONQXCVAZ YFZXUCPTLNIHMWSAVKGQDJOBER H T |
|||
HFJIDBLGMTONQUXCVAZRSKWPEY LNHMWSAVKGQDJIOBERYFZXUCPT J H |
|||
JDBLGMTONQUXCIVAZRSKWPEYHF MWAVKGQDJIOBESRYFZXUCPTLNH B A |
|||
BGMTONQUXCIVALZRSKWPEYHFJD VKQDJIOBESRYFGZXUCPTLNHMWA Y N |
|||
YFJDBGMTONQUXHCIVALZRSKWPE HMAVKQDJIOBESWRYFGZXUCPTLN H W |
|||
HIVALZRSKWPEYCFJDBGMTONQUX RYGZXUCPTLNHMFAVKQDJIOBESW Q E |
|||
QXHIVALZRSKWPUEYCFJDBGMTON SWYGZXUCPTLNHRMFAVKQDJIOBE K L |
|||
KPUEYCFJDBGMTWONQXHIVALZRS NHMFAVKQDJIOBRESWYGZXUCPTL S L |
|||
SPUEYCFJDBGMTKWONQXHIVALZR NHFAVKQDJIOBRMESWYGZXUCPTL O S |
|||
OQXHIVALZRSPUNEYCFJDBGMTKW WYZXUCPTLNHFAGVKQDJIOBRMES U A |
|||
UEYCFJDBGMTKWNOQXHIVALZRSP GVQDJIOBRMESWKYZXUCPTLNHFA J I |
|||
JBGMTKWNOQXHIDVALZRSPUEYCF OBMESWKYZXUCPRTLNHFAGVQDJI Y D |
|||
The original text was: WELLDONEISBETTERTHANWELLSAID |
|||
The encrypted text is: OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
The decrypted text is: WELLDONEISBETTERTHANWELLSAID</pre> |
|||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
|||
<syntaxhighlight lang="mathematica">ClearAll[ichaoalphabet, iMoveToFront, ChaoCipher] |
|||
ichaoalphabet = CharacterRange["A", "Z"]; |
|||
iMoveToFront[l_List, sel_] := Module[{p}, |
|||
p = FirstPosition[l, sel]; |
|||
RotateLeft[l, p - 1] |
|||
] |
|||
ChaoCipher::wrongcipheralpha = |
|||
"The cipher alphabet `1` is not a permutation of \ |
|||
\"A\"\[LongDash]\"Z\"."; |
|||
ChaoCipher::wrongplainalpha = |
|||
"The plain alphabet `1` is not a permutation of \"A\"\[LongDash]\"Z\ |
|||
\"."; |
|||
ChaoCipher[str_String, {plainalpha_List, cipheralpha_List}] := |
|||
Module[{pa, ca, plain, new, papermute, capermute, out}, |
|||
ca = ToUpperCase[cipheralpha]; |
|||
pa = ToUpperCase[plainalpha]; |
|||
If[Sort[ca] =!= Sort[ichaoalphabet], |
|||
Message[ChaoCipher::wrongcipheralpha, ca]; |
|||
$Failed |
|||
, |
|||
If[Sort[pa] =!= Sort[ichaoalphabet], |
|||
Message[ChaoCipher::wrongplainalpha, pa]; |
|||
$Failed |
|||
, |
|||
capermute = SubsetMap[RotateLeft, Range[26], Range[2, 14]]; |
|||
papermute = |
|||
SubsetMap[RotateLeft, RotateLeft[Range[26], 1], Range[3, 14]]; |
|||
plain = |
|||
Select[Characters[ToUpperCase[str]], MemberQ[ichaoalphabet, #] &]; |
|||
out = Table[ |
|||
new = Association[Thread[pa -> ca]][p]; |
|||
pa = iMoveToFront[pa, p]; |
|||
ca = iMoveToFront[ca, new]; |
|||
pa = pa[[papermute]]; |
|||
ca = ca[[capermute]]; |
|||
new |
|||
, |
|||
{p, plain} |
|||
]; |
|||
StringJoin[out] |
|||
] |
|||
] |
|||
] |
|||
ChaoCipher["WELLDONEISBETTERTHANWELLSAID",{Characters@"PTLNBQDEOYSFAVZKGJRIHWXUMC",Characters@"HXUCZVAMDSLKPEFJRIGTWOBNYQ"}] |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>OAHQHCNYNXTSZJRRHJBYHQKSOUJY</pre> |
|||
=={{header|Nim}}== |
|||
{{trans|Kotlin}} |
|||
<syntaxhighlight lang="nim">import strformat |
|||
type |
|||
Mode = enum |
|||
Encrypt |
|||
Decrypt |
|||
const lAlphabet: string = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
const rAlphabet: string = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
proc chao(text: string, mode: Mode, verbose: bool = false): string = |
|||
var left = lAlphabet |
|||
var right = rAlphabet |
|||
var eText = newSeq[char](text.len) |
|||
var temp: array[26, char] |
|||
for i in 0..<text.len: |
|||
if verbose: |
|||
echo &"{left} {right}" |
|||
var index: int |
|||
if mode == Encrypt: |
|||
index = right.find(text[i]) |
|||
eText[i] = left[index] |
|||
else: |
|||
index = left.find(text[i]) |
|||
eText[i] = right[index] |
|||
if (i == text.len - 1): |
|||
break |
|||
# permute left |
|||
for j in index..25: |
|||
temp[j - index] = left[j] |
|||
for j in 0..<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 = "" |
|||
for i in temp: |
|||
left &= $i |
|||
# permute right |
|||
for j in index..25: |
|||
temp[j - index] = right[j] |
|||
for j in 0..<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 = "" |
|||
for i in temp: |
|||
right &= $i |
|||
for i in eText: |
|||
result &= $i |
|||
var plainText = "WELLDONEISBETTERTHANWELLSAID" |
|||
echo &"The original plaintext is: {plainText}" |
|||
echo "\nThe left and right alphabets after each permutation during encryption are:\n" |
|||
var cipherText = chao(plainText, Encrypt, true) |
|||
echo &"\nThe ciphertext is: {cipherText}" |
|||
var plainText2 = chao(cipherText, Decrypt, false) |
|||
echo &"\nThe recovered plaintext is: {plainText2}"</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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 |
|||
</pre> |
|||
===Another implementation=== |
|||
Using functions from the stdlib instead of manual array manipulations: |
|||
<syntaxhighlight lang="nim">import std/[algorithm, strutils] |
|||
type |
|||
Mode = enum |
|||
Encrypt |
|||
Decrypt |
|||
const |
|||
lAlphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
rAlphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
proc chao(text: string; mode: Mode; verbose = false): string = |
|||
var |
|||
left = lAlphabet |
|||
right = rAlphabet |
|||
eText = newSeq[char](text.len) |
|||
for i in 0 ..< text.len: |
|||
if verbose: |
|||
echo left, " ", right |
|||
var index: int |
|||
if mode == Encrypt: |
|||
index = right.find(text[i]) |
|||
eText[i] = left[index] |
|||
else: |
|||
index = left.find(text[i]) |
|||
eText[i] = right[index] |
|||
if i == text.len - 1: |
|||
break |
|||
# permute left |
|||
left.rotateLeft(index) |
|||
left.rotateLeft(1..13, 1) |
|||
# permute right |
|||
right.rotateLeft(index + 1) |
|||
right.rotateLeft(2..13, 1) |
|||
result = eText.join() |
|||
let plainText = "WELLDONEISBETTERTHANWELLSAID" |
|||
echo "The original plaintext is: ", plainText |
|||
echo "\nThe left and right alphabets after each permutation during encryption are:\n" |
|||
let cipherText = chao(plainText, Encrypt, true) |
|||
echo "\nThe ciphertext is: ", cipherText |
|||
let plainText2 = chao(cipherText, Decrypt, false) |
|||
echo "\nThe recovered plaintext is: ", plainText2</syntaxhighlight> |
|||
Same output as above. |
|||
=={{header|Objeck}}== |
=={{header|Objeck}}== |
||
{{trans|Kotlin}} |
{{trans|Kotlin}} |
||
< |
<syntaxhighlight lang="objeck">class Chaocipher { |
||
L_ALPHABET : static : Char[]; |
L_ALPHABET : static : Char[]; |
||
R_ALPHABET : static : Char[]; |
R_ALPHABET : static : Char[]; |
||
Line 1,143: | Line 2,600: | ||
enum Mode { ENCRYPT, DECRYPT } |
enum Mode { ENCRYPT, DECRYPT } |
||
}</ |
}</syntaxhighlight> |
||
{{output}} |
{{output}} |
||
Line 1,183: | Line 2,640: | ||
The recovered plaintext is: WELLDONEISBETTERTHANWELLSAID |
The recovered plaintext is: WELLDONEISBETTERTHANWELLSAID |
||
</pre> |
</pre> |
||
=={{header|Pascal}}== |
|||
{{works with|Extended Pascal}} |
|||
<syntaxhighlight lang="pascal">program chaocipher(input, output); |
|||
const |
|||
{ This denotes a `set` literal: } |
|||
alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', |
|||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; |
|||
{ The `card` function is an Extended Pascal (ISO 10206) extension. } |
|||
alphabetCardinality = card(alphabet); |
|||
{ 1st character denotes “zenith”. } |
|||
zenith = 1; |
|||
{ In a 26-character alphabet the 14th character denotes “nadir”. } |
|||
nadir = alphabetCardinality div 2 + 1; |
|||
{ For simplicity use compile-time-defined maximum lengths. } |
|||
messageMaximumLength = 80; |
|||
type |
|||
{ This “discriminates” the Extended Pascal schema data type `string` to be } |
|||
{ capable of holding strings up to `alphabetCardinality` `char` values. } |
|||
map = string(alphabetCardinality); |
|||
{ Variables of this data type can only assume integer values within 1..26: } |
|||
mapCharacterIndex = 1..alphabetCardinality; |
|||
{ Later used as a buffer for the input/output. } |
|||
message = string(messageMaximumLength); |
|||
messageCharacterIndex = 1..messageMaximumLength; |
|||
{ Stores a key for the Chaocipher algorithm. } |
|||
key = record |
|||
cipherText: map; |
|||
plainText: map; |
|||
end; |
|||
{ --- auxilliary routines ---------------------------------------------- } |
|||
{ |
|||
\brief verifies that a key is valid for the Chaocipher |
|||
\param sample a potential `key` for a Chaocipher |
|||
\return `true` iff \param sample is an acceptable `key` |
|||
} |
|||
{ `protected` (Extended Pascal extension) denotes an immutable parameter. } |
|||
function isValid(protected sample: key): Boolean; |
|||
{ Determines whether a `map` contains all characters of `alphabet`. } |
|||
{ Nesting this function allows for a neat expression below. } |
|||
function isComplete(protected text: map): Boolean; |
|||
var |
|||
i: integer; |
|||
{ `value []` will initialize this variable to an empty set value. } |
|||
{ This is an Extended Pascal (ISO 10206) extension. } |
|||
s: set of char value []; |
|||
begin |
|||
{ NB: In Pascal `for`-loop limits are inclusive. } |
|||
for i := 1 to length(text) do |
|||
begin |
|||
{ This adds the set containing one character to the set `s`. } |
|||
s := s + [text[i]] |
|||
end; |
|||
isComplete := card(s) = alphabetCardinality |
|||
end; |
|||
begin |
|||
{ This way `sample.cipherText` can be simply written as `cipherText`. } |
|||
with sample do |
|||
begin |
|||
{ `and_then` is an EP extension indicating “lazy evaluation”. } |
|||
isValid := (alphabetCardinality > 8) and_then |
|||
isComplete(cipherText) and_then isComplete(plainText) |
|||
end |
|||
end; |
|||
{ |
|||
\brief permutes a key for the next encryption/decryption step |
|||
\param shift the index of the characters just substituted |
|||
} |
|||
{ `var` means the parameter value will be modified _at_ the call site. } |
|||
procedure permute(var state: key; protected shift: mapCharacterIndex); |
|||
begin |
|||
with state do |
|||
begin |
|||
{ Indices in `cipherText[1..pred(shift)]` _must_ be non-descending: } |
|||
if shift > 1 then |
|||
begin |
|||
cipherText := subStr(cipherText, shift) + cipherText[1..pred(shift)] |
|||
{ `subStr(str, ini)` is equivalent to `str[ini..length(str)]`. } |
|||
end; |
|||
{ Likewise, `succ(shift)` must be a valid index in `plainText`: } |
|||
if shift < alphabetCardinality then |
|||
begin |
|||
plainText := subStr(plainText, succ(shift)) + plainText[1..shift] |
|||
end; |
|||
{ If it does _not_ _alter_ the _entire_ string’s _length_, you can } |
|||
{ modify parts of a string like this (Extended Pascal extension): } |
|||
cipherText[zenith+1..nadir] := cipherText[zenith+2..nadir] + cipherText[zenith+1]; |
|||
plainText[zenith+2..nadir] := plainText[zenith+3..nadir] + plainText[zenith+2] |
|||
end |
|||
end; |
|||
{ --- the core routine of the algorithm -------------------------------- } |
|||
{ |
|||
\brief performs Chaocipher common steps |
|||
\param line the message to encrypt/decrypt |
|||
\param state the initial key to start encrpytion/decryption with |
|||
\param locate a function determining the 2-tuple index in the key |
|||
\param substitute the procedure substituting the correct characters |
|||
} |
|||
procedure chaocipher( |
|||
var line: message; |
|||
var state: key; |
|||
{ These are “routine parameters”. Essentially the address of a routine } |
|||
{ matching the specified routine signature is passed to `chaocipher`. } |
|||
function locate(protected i: messageCharacterIndex): mapCharacterIndex; |
|||
procedure substitute( |
|||
protected i: messageCharacterIndex; |
|||
protected z: mapCharacterIndex |
|||
) |
|||
); |
|||
var |
|||
{ For demonstration purposes: In this program } |
|||
{ `line.capacity` refers to `messageMaximumLength`. } |
|||
i: 1..line.capacity; |
|||
substitutionPairIndex: mapCharacterIndex; |
|||
begin |
|||
{ Don’t trust user input, even though this is just a RosettaCode example. } |
|||
if not isValid(state) then |
|||
begin |
|||
writeLn('Error: Key is invalid. Got:'); |
|||
writeLn('Cipher text: ', state.cipherText); |
|||
writeLn(' Plain text: ', state.plainText); |
|||
halt |
|||
end; |
|||
for i := 1 to length(line) do |
|||
begin |
|||
{ We’ll better skip characters that aren’t in the `alphabet`. } |
|||
if line[i] in alphabet then |
|||
begin |
|||
{ Here you see the beauty of using routine parameters. } |
|||
{ Depending on whether we’re encrypting or decrypting, } |
|||
{ you need to find a character in the `cipherText` or } |
|||
{ `plainText` key value respectively, yet the basic order |
|||
{ of the steps are still the same. } |
|||
substitutionPairIndex := locate(i); |
|||
substitute(i, substitutionPairIndex); |
|||
permute(state, substitutionPairIndex) |
|||
end |
|||
end |
|||
end; |
|||
{ --- entry routines --------------------------------------------------- } |
|||
{ |
|||
\brief encrypts a message according to Chaocipher |
|||
\param line a message to encrypt |
|||
\param state the key to begin with |
|||
\return the encrypted message \param line using the provided key |
|||
} |
|||
{ Note: without `var` or `protected` both `encrypt` and `decrypt`get } |
|||
{ and have their own independent copies of the parameter values. } |
|||
function encrypt(line: message; state: key): message; |
|||
function encryptor(protected i: messageCharacterIndex): mapCharacterIndex; |
|||
begin |
|||
encryptor := index(state.plainText, line[i]) |
|||
end; |
|||
procedure substitutor( |
|||
protected i: messageCharacterIndex; |
|||
protected z: mapCharacterIndex |
|||
); |
|||
begin |
|||
line[i] := state.cipherText[z] |
|||
end; |
|||
begin |
|||
chaocipher(line, state, encryptor, substitutor); |
|||
encrypt := line |
|||
end; |
|||
{ |
|||
\brief decrypts a message according to Chaocipher |
|||
\param line the encrypted message |
|||
\param state the key to begin with |
|||
\return the decrypted message \param line using the provided key |
|||
} |
|||
function decrypt(line: message; state: key): message; |
|||
function decryptor(protected i: messageCharacterIndex): mapCharacterIndex; |
|||
begin |
|||
decryptor := index(state.cipherText, line[i]) |
|||
end; |
|||
procedure substitutor( |
|||
protected i: messageCharacterIndex; |
|||
protected z: mapCharacterIndex |
|||
); |
|||
begin |
|||
line[i] := state.plainText[z] |
|||
end; |
|||
begin |
|||
chaocipher(line, state, decryptor, substitutor); |
|||
decrypt := line |
|||
end; |
|||
{ === MAIN ============================================================= } |
|||
var |
|||
exampleKey: key; |
|||
line: message; |
|||
begin |
|||
{ Instead of writing `exampleKey.cipherText := '…', you can } |
|||
{ write in Extended Pascal a `record` literal like this: } |
|||
exampleKey := key[ |
|||
cipherText: 'HXUCZVAMDSLKPEFJRIGTWOBNYQ'; |
|||
plainText: 'PTLNBQDEOYSFAVZKGJRIHWXUMC'; |
|||
]; |
|||
{ `EOF` is shorthand for `EOF(input)`. } |
|||
while not EOF do |
|||
begin |
|||
{ `readLn(line)` is shorthand for `readLn(input, line)`. } |
|||
readLn(line); |
|||
line := encrypt(line, exampleKey); |
|||
writeLn(decrypt(line, exampleKey)); |
|||
{ Likewise, `writeLn(line)` is short for `writeLn(output, line)`. } |
|||
writeLn(line) |
|||
end |
|||
end.</syntaxhighlight> |
|||
{{in}} |
|||
WELLDONEISBETTERTHANWELLSAID |
|||
{{out}} |
|||
WELLDONEISBETTERTHANWELLSAID |
|||
OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
{{trans| |
{{trans|Raku}} |
||
Since <tt>rotate</tt> is not a built-in in Perl, using a custom one, not general-purpose but sufficient for this task. |
Since <tt>rotate</tt> is not a built-in in Perl, using a custom one, not general-purpose but sufficient for this task. |
||
<syntaxhighlight lang="perl" line>use strict; |
|||
<lang perl>sub init { |
|||
use warnings; |
|||
my(@left,@right,$e_msg,$d_msg); |
|||
sub init { |
|||
@left = split '', 'HXUCZVAMDSLKPEFJRIGTWOBNYQ'; |
@left = split '', 'HXUCZVAMDSLKPEFJRIGTWOBNYQ'; |
||
@right = split '', 'PTLNBQDEOYSFAVZKGJRIHWXUMC'; |
@right = split '', 'PTLNBQDEOYSFAVZKGJRIHWXUMC'; |
||
Line 1,223: | Line 2,910: | ||
sub rotate { |
sub rotate { |
||
my @list = @{ shift() }; |
|||
my($n,$s,$e) = @_; |
my($n,$s,$e) = @_; |
||
$s ? @list[0..$s-1, $s+$n..$e+$n-1, $s..$s+$n-1, $e+1..$#list] |
|||
: @list[$n..$#list, 0..$n-1] |
|||
} |
} |
||
init; $e_msg .= encode |
init; $e_msg .= encode $_ for split '', 'WELLDONEISBETTERTHANWELLSAID'; |
||
init; $d_msg .= decode |
init; $d_msg .= decode $_ for split '', $e_msg; |
||
print "$e_msg\n"; |
print "$e_msg\n$d_msg\n";</syntaxhighlight> |
||
print "$d_msg\n";</lang> |
|||
{{out}} |
{{out}} |
||
<pre>OMUUADCMTLZMXXMGXWPCOMUULPTA |
|||
<pre>OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
WELLDONEISBETTERTHANWELLSAID</pre> |
|||
=={{header|Perl 6}}== |
|||
{{works with|Rakudo|2018.03}} |
|||
<lang perl6>my @left; |
|||
my @right; |
|||
sub reset { |
|||
@left = <HXUCZVAMDSLKPEFJRIGTWOBNYQ>.comb; |
|||
@right = <PTLNBQDEOYSFAVZKGJRIHWXUMC>.comb; |
|||
} |
|||
sub encode ($letter) { |
|||
my $index = @right.first: $letter.uc, :k; |
|||
my $enc = @left[$index]; |
|||
$index.&permute; |
|||
$enc |
|||
} |
|||
sub decode ($letter) { |
|||
my $index = @left.first: $letter.uc, :k; |
|||
my $dec = @right[$index]; |
|||
$index.&permute; |
|||
$dec |
|||
} |
|||
sub permute ($index) { |
|||
@left.=rotate: $index; |
|||
@left[1..13].=rotate; |
|||
@right.=rotate: $index + 1; |
|||
@right[2..13].=rotate; |
|||
} |
|||
reset; |
|||
say 'WELLDONEISBETTERTHANWELLSAID'.comb».&encode.join; |
|||
reset; |
|||
say 'OAHQHCNYNXTSZJRRHJBYHQKSOUJY'.comb».&decode.join;</lang> |
|||
{{out}} |
|||
<pre>OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
WELLDONEISBETTERTHANWELLSAID</pre> |
WELLDONEISBETTERTHANWELLSAID</pre> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Originally translated from C, but ended up more of a direct implementation of the algorithm in the pdf. |
Originally translated from C, but ended up more of a direct implementation of the algorithm in the pdf. |
||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<lang Phix>-- demo\rosetta\Chao_cipher.exw |
|||
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Chao_cipher.exw</span> |
|||
constant l_alphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ", |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
r_alphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">l_alphabet</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"HXUCZVAMDSLKPEFJRIGTWOBNYQ"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">r_alphabet</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"PTLNBQDEOYSFAVZKGJRIHWXUMC"</span> |
|||
enum ENCRYPT, DECRYPT |
|||
<span style="color: #008080;">enum</span> <span style="color: #000000;">ENCRYPT</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">DECRYPT</span> |
|||
function chao_cipher(string in, integer mode, bool show_steps) |
|||
integer len = length(in) |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">chao_cipher</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">mode</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">show_steps</span><span style="color: #0000FF;">)</span> |
|||
string out = repeat(' ',len) |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> |
|||
string left = l_alphabet, |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">out</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">' '</span><span style="color: #0000FF;">,</span><span style="color: #000000;">len</span><span style="color: #0000FF;">),</span> |
|||
right = r_alphabet |
|||
<span style="color: #000000;">left</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">l_alphabet</span><span style="color: #0000FF;">,</span> |
|||
for i=1 to len do |
|||
<span style="color: #000000;">right</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r_alphabet</span> |
|||
if show_steps then printf(1,"%s %s\n", {left, right}) end if |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">len</span> <span style="color: #008080;">do</span> |
|||
integer index = find(in[i],iff(mode==ENCRYPT?right:left)) |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">show_steps</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">left</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">right</span><span style="color: #0000FF;">})</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
out[i] = iff(mode==ENCRYPT?left:right)[index] |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">index</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mode</span><span style="color: #0000FF;">==</span><span style="color: #000000;">ENCRYPT</span><span style="color: #0000FF;">?</span><span style="color: #000000;">right</span><span style="color: #0000FF;">:</span><span style="color: #000000;">left</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #000000;">out</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mode</span><span style="color: #0000FF;">==</span><span style="color: #000000;">ENCRYPT</span><span style="color: #0000FF;">?</span><span style="color: #000000;">left</span><span style="color: #0000FF;">:</span><span style="color: #000000;">right</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">index</span><span style="color: #0000FF;">]</span> |
|||
if i==len then exit end if |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">==</span><span style="color: #000000;">len</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
/* permute left */ |
|||
left = left[index..26]&left[1..index-1] |
|||
<span style="color: #000080;font-style:italic;">/* permute left */</span> |
|||
left[2..14] = left[3..14]&left[2] |
|||
<span style="color: #000000;">left</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">left</span><span style="color: #0000FF;">[</span><span style="color: #000000;">index</span><span style="color: #0000FF;">..</span><span style="color: #000000;">26</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">left</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">index</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #000000;">left</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">..</span><span style="color: #000000;">14</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">left</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">..</span><span style="color: #000000;">14</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">left</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> |
|||
/* permute right */ |
|||
right = right[index+1..26]&right[1..index] |
|||
right[3..14] = right[4..14]&right[3] |
|||
end for |
|||
return out |
|||
end function |
|||
<span style="color: #000080;font-style:italic;">/* permute right */</span> |
|||
string plain_text = "WELLDONEISBETTERTHANWELLSAID" |
|||
<span style="color: #000000;">right</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">right</span><span style="color: #0000FF;">[</span><span style="color: #000000;">index</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">26</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">right</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">index</span><span style="color: #0000FF;">]</span> |
|||
printf(1,"The original plaintext is : %s\n", {plain_text}) |
|||
<span style="color: #000000;">right</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">..</span><span style="color: #000000;">14</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">right</span><span style="color: #0000FF;">[</span><span style="color: #000000;">4</span><span style="color: #0000FF;">..</span><span style="color: #000000;">14</span><span style="color: #0000FF;">]&</span><span style="color: #000000;">right</span><span style="color: #0000FF;">[</span><span style="color: #000000;">3</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
--printf(1,"\nThe left and right alphabets after each permutation"& |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">out</span> |
|||
-- " during encryption are :\n\n") |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
--string cipher_text = chao_cipher(plain_text, ENCRYPT, true) |
|||
string cipher_text = chao_cipher(plain_text, ENCRYPT, false) |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">plain_text</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"WELLDONEISBETTERTHANWELLSAID"</span> |
|||
printf(1,"\nThe ciphertext is : %s\n", {cipher_text}) |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"The original plaintext is : %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">plain_text</span><span style="color: #0000FF;">})</span> |
|||
string plain_text2 = chao_cipher(cipher_text, DECRYPT, false) |
|||
<span style="color: #000080;font-style:italic;">--printf(1,"\nThe left and right alphabets after each permutation"& |
|||
printf(1,"\nThe recovered plaintext is : %s\n", {plain_text2})</lang> |
|||
-- " during encryption are :\n\n") |
|||
--string cipher_text = chao_cipher(plain_text, ENCRYPT, true)</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">cipher_text</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">chao_cipher</span><span style="color: #0000FF;">(</span><span style="color: #000000;">plain_text</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ENCRYPT</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nThe ciphertext is : %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">cipher_text</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">plain_text2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">chao_cipher</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cipher_text</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">DECRYPT</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nThe recovered plaintext is : %s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">plain_text2</span><span style="color: #0000FF;">})</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 1,328: | Line 2,977: | ||
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID |
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID |
||
</pre> |
</pre> |
||
=={{header|Python}}== |
=={{header|Python}}== |
||
===Procedural=== |
===Procedural=== |
||
< |
<syntaxhighlight lang="python"># Python3 implementation of Chaocipher |
||
# left wheel = ciphertext wheel |
# left wheel = ciphertext wheel |
||
# right wheel = plaintext wheel |
# right wheel = plaintext wheel |
||
Line 1,406: | Line 3,054: | ||
return lalph, ralph |
return lalph, ralph |
||
main()</ |
main()</syntaxhighlight> |
||
<pre>L: HXUCZVAMDSLKPEFJRIGTWOBNYQ |
<pre>L: HXUCZVAMDSLKPEFJRIGTWOBNYQ |
||
R: PTLNBQDEOYSFAVZKGJRIHWXUMC |
R: PTLNBQDEOYSFAVZKGJRIHWXUMC |
||
Line 1,452: | Line 3,100: | ||
{{Trans|Haskell}} |
{{Trans|Haskell}} |
||
{{Works with|Python|3.7}} |
{{Works with|Python|3.7}} |
||
< |
<syntaxhighlight lang="python">'''Chaocipher''' |
||
from itertools import chain, cycle, islice |
from itertools import chain, cycle, islice |
||
Line 1,637: | Line 3,285: | ||
# MAIN --- |
# MAIN --- |
||
if __name__ == '__main__': |
if __name__ == '__main__': |
||
main()</ |
main()</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>WELLDONEISBETTERTHANWELLSAID |
<pre>WELLDONEISBETTERTHANWELLSAID |
||
Line 1,643: | Line 3,291: | ||
WELLDONEISBETTERTHANWELLSAID</pre> |
WELLDONEISBETTERTHANWELLSAID</pre> |
||
=={{header|QBasic}}== |
|||
{{trans|BASIC}} |
|||
<syntaxhighlight lang="qbasic">DECLARE FUNCTION AlphaLeft$ (ct$, pt$, CharPos!) |
|||
DECLARE FUNCTION AlphaRight$ (ct$, pt$, CharPos!) |
|||
DECLARE FUNCTION Decode$ (Text$, ct$, pt$) |
|||
DECLARE FUNCTION Encode$ (Text$, ct$, pt$) |
|||
CLS |
|||
' Deciphering a Chaocipher-encrypted message is identical to the steps used |
|||
' for enciphering. The sole difference is that the decipherer locates the |
|||
' known ciphertext letter in the left (ct$) alphabet, with the plaintext |
|||
' letter being the corresponding letter in the right (pt$) alphabet |
|||
' |
|||
' Alphabet permuting is identical in enciphering and deciphering |
|||
' Start of Main Code |
|||
' LEFT (Cipher Text$): HXUCZVAMDSLKPEFJRIGTWOBNYQ |
|||
tLeft$ = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
' RIGHT (Plain Text$): PTLNBQDEOYSFAVZKGJRIHWXUMC |
|||
tRight$ = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
' Cipher Message (Used to verify a good encoding) |
|||
cText$ = "OAHQHCNYNXTSZJRRHJBYHQKSOUJY" |
|||
' Plain Text$ Message |
|||
pText$ = "WELLDONEISBETTERTHANWELLSAID" |
|||
PRINT " Plain Text$: "; pText$ |
|||
PRINT |
|||
ctLeft$ = tLeft$ |
|||
ptRight$ = tRight$ |
|||
' Final Cipher Text$ |
|||
eText$ = Encode$(pText$, ctLeft$, ptRight$) |
|||
PRINT " Cipher Text$: "; eText$ |
|||
PRINT |
|||
IF eText$ = cText$ THEN PRINT "Successful" ELSE PRINT "Failed" |
|||
ctLeft$ = tLeft$ |
|||
ptRight$ = tRight$ |
|||
dText$ = Decode$(eText$, ctLeft$, ptRight$) |
|||
PRINT |
|||
PRINT " Plain Text$: "; dText$ |
|||
PRINT |
|||
IF dText$ = pText$ THEN PRINT "Successful" ELSE PRINT "Failed" |
|||
END |
|||
' Left Alphabet |
|||
FUNCTION AlphaLeft$ (ct$, pt$, CharPos) |
|||
tStr$ = ct$ |
|||
' 1. Shift the entire left alphabet cyclically so the ciphertext letter |
|||
' just enciphered is positioned at the zenith (i.e., position 1). |
|||
tStr$ = RIGHT$(ct$, LEN(ct$) - CharPos + 1) + LEFT$(ct$, CharPos - 1) |
|||
' 2. Extract the letter found at position zenith+1 (i.e., the letter to |
|||
' the right of the zenith), taking it out of the alphabet, temporarily |
|||
' leaving an unfilled "Hole$" |
|||
Hole$ = MID$(tStr$, 2, 1) |
|||
MID$(tStr$, 2, 1) = " " |
|||
' 3. Shift all letters in positions zenith+2 up to, and including, the |
|||
' nadir (zenith+13), moving them one position to the left |
|||
tStr$ = LEFT$(tStr$, 1) + MID$(tStr$, 3, 12) + " " + RIGHT$(tStr$, 12) |
|||
' 4. Insert the just-extracted letter into the nadir position |
|||
' (i.e., zenith+13) |
|||
MID$(tStr$, 14, 1) = Hole$ |
|||
AlphaLeft$ = tStr$ |
|||
END FUNCTION |
|||
' Right Alphabet |
|||
FUNCTION AlphaRight$ (ct$, pt$, CharPos) |
|||
tStr$ = pt$ |
|||
' 1. Shift the entire right alphabet cyclically so the plaintext letter |
|||
' just enciphered is positioned at the zenith. |
|||
tStr$ = RIGHT$(tStr$, LEN(tStr$) - CharPos + 1) + LEFT$(tStr$, CharPos - 1) |
|||
' 2. Now shift the entire alphabet one more position to the left (i.e., |
|||
' the leftmost letter moves cyclically to the far right), moving a new |
|||
' letter into the zenith position. |
|||
tStr$ = RIGHT$(tStr$, 25) + LEFT$(tStr$, 1) |
|||
' 3. Extract the letter at position zenith+2, taking it out of the |
|||
' alphabet, temporarily leaving an unfilled "Hole$". |
|||
Hole$ = MID$(tStr$, 3, 1) |
|||
MID$(tStr$, 3, 1) = " ": |
|||
' 4. Shift all letters beginning with zenith+3 up to, and including, the |
|||
' nadir (zenith+13), moving them one position to the left. |
|||
tStr$ = LEFT$(tStr$, 2) + MID$(tStr$, 4, 11) + " " + RIGHT$(tStr$, 12) |
|||
' 5. Insert the just-extracted letter into the nadir position (zenith+13) |
|||
MID$(tStr$, 14, 1) = Hole$ |
|||
AlphaRight$ = tStr$ |
|||
END FUNCTION |
|||
FUNCTION Decode$ (Text$, ct$, pt$) |
|||
tStr$ = "" |
|||
FOR t = 1 TO LEN(Text$) |
|||
Char$ = MID$(Text$, t, 1) |
|||
CharPos = INSTR(ct$, Char$) |
|||
ct$ = AlphaLeft$(ct$, pt$, CharPos) |
|||
pt$ = AlphaRight$(ct$, pt$, CharPos) |
|||
tStr$ = tStr$ + RIGHT$(pt$, 1) |
|||
NEXT |
|||
Decode$ = tStr$ |
|||
END FUNCTION |
|||
FUNCTION Encode$ (Text$, ct$, pt$) |
|||
tStr$ = "" |
|||
FOR t = 1 TO LEN(Text$) |
|||
Char$ = MID$(Text$, t, 1) |
|||
CharPos = INSTR(pt$, Char$) |
|||
ct$ = AlphaLeft$(ct$, pt$, CharPos) |
|||
pt$ = AlphaRight$(ct$, pt$, CharPos) |
|||
tStr$ = tStr$ + LEFT$(ct$, 1) |
|||
NEXT |
|||
Encode$ = tStr$ |
|||
END FUNCTION |
|||
</syntaxhighlight> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{works with|Rakudo|2018.03}} |
|||
<syntaxhighlight lang="raku" line>my @left; |
|||
my @right; |
|||
sub reset { |
|||
@left = <HXUCZVAMDSLKPEFJRIGTWOBNYQ>.comb; |
|||
@right = <PTLNBQDEOYSFAVZKGJRIHWXUMC>.comb; |
|||
} |
|||
sub encode ($letter) { |
|||
my $index = @right.first: $letter.uc, :k; |
|||
my $enc = @left[$index]; |
|||
$index.&permute; |
|||
$enc |
|||
} |
|||
sub decode ($letter) { |
|||
my $index = @left.first: $letter.uc, :k; |
|||
my $dec = @right[$index]; |
|||
$index.&permute; |
|||
$dec |
|||
} |
|||
sub permute ($index) { |
|||
@left.=rotate: $index; |
|||
@left[1..13].=rotate; |
|||
@right.=rotate: $index + 1; |
|||
@right[2..13].=rotate; |
|||
} |
|||
reset; |
|||
say 'WELLDONEISBETTERTHANWELLSAID'.comb».&encode.join; |
|||
reset; |
|||
say 'OAHQHCNYNXTSZJRRHJBYHQKSOUJY'.comb».&decode.join;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
|||
WELLDONEISBETTERTHANWELLSAID</pre> |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
< |
<syntaxhighlight lang="ruby">txt = "WELLDONEISBETTERTHANWELLSAID" |
||
@left = "HXUCZVAMDSLKPEFJRIGTWOBNYQ".chars |
@left = "HXUCZVAMDSLKPEFJRIGTWOBNYQ".chars |
||
@right = "PTLNBQDEOYSFAVZKGJRIHWXUMC".chars |
@right = "PTLNBQDEOYSFAVZKGJRIHWXUMC".chars |
||
Line 1,663: | Line 3,497: | ||
puts txt.each_char.map{|c| encrypt(c) }.join |
puts txt.each_char.map{|c| encrypt(c) }.join |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre>OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
<pre>OAHQHCNYNXTSZJRRHJBYHQKSOUJY |
||
</pre> |
</pre> |
||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
< |
<syntaxhighlight lang="rust">const LEFT_ALPHABET_CT: &str = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"; |
||
const RIGHT_ALPHABET_PT: &str = "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
const RIGHT_ALPHABET_PT: &str = "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
||
const ZENITH: usize = 0; |
const ZENITH: usize = 0; |
||
Line 1,700: | Line 3,533: | ||
println!("Plaintext: {}", SEQUENCE); |
println!("Plaintext: {}", SEQUENCE); |
||
println!("Ciphertext: {}", ciphertext); |
println!("Ciphertext: {}", ciphertext); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Plaintext: WELLDONEISBETTERTHANWELLSAID |
<pre>Plaintext: WELLDONEISBETTERTHANWELLSAID |
||
Ciphertext: OAHQHCNYNXTSZJRRHJBYHQKSOUJY</pre> |
Ciphertext: OAHQHCNYNXTSZJRRHJBYHQKSOUJY</pre> |
||
=={{header|Tailspin}}== |
=={{header|Tailspin}}== |
||
< |
<syntaxhighlight lang="tailspin"> |
||
templates chaocipher |
templates chaocipher&{left:,right:,decode:} |
||
templates permute |
templates permute |
||
def ctshift: [ $@chaocipher.ct($.. |
def ctshift: [ $@chaocipher.ct($..last)..., $@chaocipher.ct(1..$-1)...]; |
||
def p1: $ mod 26 + 1; |
def p1: $ mod 26 + 1; |
||
def ptshift: [ $@chaocipher.pt($p1.. |
def ptshift: [ $@chaocipher.pt($p1..last)..., $@chaocipher.pt(1..$p1-1)...]; |
||
..|@chaocipher: { ct: [ $ctshift(1), $ctshift(3..14)..., $ctshift(2), $ctshift(15.. |
..|@chaocipher: { ct: [ $ctshift(1), $ctshift(3..14)..., $ctshift(2), $ctshift(15..last)...], |
||
pt: [ $ptshift(1..2)..., $ptshift(4..14)..., $ptshift(3), $ptshift(15.. |
pt: [ $ptshift(1..2)..., $ptshift(4..14)..., $ptshift(3), $ptshift(15..last)...] }; |
||
end permute |
end permute |
||
@: {ct:[ $left... ], pt: [ $right... ], result:[]}; |
@: {ct:[ $left... ], pt: [ $right... ], result:[]}; |
||
$... -> # |
$... -> # |
||
'$@.result...;' ! |
'$@.result...;' ! |
||
<?($decode <0>)> |
when <?($decode <=0>)> do |
||
def plain: $; |
def plain: $; |
||
def index: $@.pt -> [i](<$plain> $i!) -> $(1); |
def index: $@.pt -> \[i](<=$plain> $i!\) -> $(1); |
||
..|@.result: $@.ct($index); |
..|@.result: $@.ct($index); |
||
$index -> permute -> !VOID |
$index -> permute -> !VOID |
||
otherwise |
|||
<> |
|||
def cipher: $; |
def cipher: $; |
||
def index: $@.ct -> [i](<$cipher> $i!) -> $(1); |
def index: $@.ct -> \[i](<=$cipher> $i!\) -> $(1); |
||
..|@.result: $@.pt($index); |
..|@.result: $@.pt($index); |
||
$index -> permute -> !VOID |
$index -> permute -> !VOID |
||
end chaocipher |
end chaocipher |
||
'WELLDONEISBETTERTHANWELLSAID' -> chaocipher |
'WELLDONEISBETTERTHANWELLSAID' -> chaocipher&{left:'HXUCZVAMDSLKPEFJRIGTWOBNYQ', right:'PTLNBQDEOYSFAVZKGJRIHWXUMC',decode:0} -> '$; |
||
' -> !OUT::write |
' -> !OUT::write |
||
'OAHQHCNYNXTSZJRRHJBYHQKSOUJY' -> chaocipher |
'OAHQHCNYNXTSZJRRHJBYHQKSOUJY' -> chaocipher&{left:'HXUCZVAMDSLKPEFJRIGTWOBNYQ', right:'PTLNBQDEOYSFAVZKGJRIHWXUMC',decode:1} -> '$; |
||
' -> !OUT::write |
' -> !OUT::write |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 1,744: | Line 3,576: | ||
WELLDONEISBETTERTHANWELLSAID |
WELLDONEISBETTERTHANWELLSAID |
||
</pre> |
</pre> |
||
=={{header|Visual Basic .NET}}== |
=={{header|Visual Basic .NET}}== |
||
{{trans|C#}} |
{{trans|C#}} |
||
< |
<syntaxhighlight lang="vbnet">Module Module1 |
||
ReadOnly L_ALPHABET As String = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
ReadOnly L_ALPHABET As String = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
||
Line 1,824: | Line 3,655: | ||
End Sub |
End Sub |
||
End Module</ |
End Module</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>The original plaintext is : WELLDONEISBETTERTHANWELLSAID |
<pre>The original plaintext is : WELLDONEISBETTERTHANWELLSAID |
||
Line 1,862: | Line 3,693: | ||
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID</pre> |
The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID</pre> |
||
=={{header|V (Vlang)}}== |
|||
{{trans|Go}} |
|||
<syntaxhighlight lang="v (vlang)">type Mode = int |
|||
const( |
|||
encrypt = Mode(0) |
|||
decrypt = Mode(1) |
|||
) |
|||
const( |
|||
l_alphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
r_alphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
) |
|||
fn chao(text string, mode Mode, show_steps bool) string { |
|||
len := text.len |
|||
if text.bytes().len != len { |
|||
println("Text contains non-ASCII characters") |
|||
return "" |
|||
} |
|||
mut left := l_alphabet |
|||
mut right := r_alphabet |
|||
mut e_text := []u8{len: len} |
|||
mut temp := []u8{len: 26} |
|||
for i in 0..len { |
|||
if show_steps { |
|||
println('$left $right') |
|||
} |
|||
mut index := 0 |
|||
if mode == encrypt { |
|||
index = right.index_u8(text[i]) |
|||
e_text[i] = left[index] |
|||
} else { |
|||
index = left.index_u8(text[i]) |
|||
e_text[i] = right[index] |
|||
} |
|||
if i == len - 1 { |
|||
break |
|||
} |
|||
// permute left |
|||
for j in index..26 { |
|||
temp[j - index] = left[j] |
|||
} |
|||
for j in 0..index { |
|||
temp[26 - index + j] = left[j] |
|||
} |
|||
mut store := temp[1] |
|||
for j in 2..14 { |
|||
temp[j - 1] = temp[j] |
|||
} |
|||
temp[13] = store |
|||
left = temp.bytestr() |
|||
// permute right |
|||
for j in index..26 { |
|||
temp[j - index] = right[j] |
|||
} |
|||
for j in 0..index { |
|||
temp[26 - index + j] = right[j] |
|||
} |
|||
store = temp[0] |
|||
for j in 1..26 { |
|||
temp[j - 1] = temp[j] |
|||
} |
|||
temp[25] = store |
|||
store = temp[2] |
|||
for j in 3..14 { |
|||
temp[j - 1] = temp[j] |
|||
} |
|||
temp[13] = store |
|||
right = temp.bytestr() |
|||
} |
|||
return e_text.bytestr() |
|||
} |
|||
fn main() { |
|||
plain_text := "WELLDONEISBETTERTHANWELLSAID" |
|||
println("The original plaintext is : $plain_text") |
|||
print("\nThe left and right alphabets after each permutation ") |
|||
println("during encryption are :\n") |
|||
cypher_text := chao(plain_text, encrypt, true) |
|||
println("\nThe ciphertext is : $cypher_text") |
|||
plain_text2 := chao(cypher_text, decrypt, false) |
|||
println("\nThe recovered plaintext is : $plain_text2") |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Same as Kotlin Entry</pre> |
|||
=={{header|Wren}}== |
|||
{{trans|Kotlin}} |
|||
<syntaxhighlight lang="wren">class Chao { |
|||
static encrypt { 0 } |
|||
static decrypt { 1 } |
|||
static exec(text, mode, showSteps) { |
|||
var len = text.count |
|||
if (len != text.bytes.count) Fiber.abort("Text contains non-ASCII characters.") |
|||
var left = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" |
|||
var right = "PTLNBQDEOYSFAVZKGJRIHWXUMC" |
|||
var eText = List.filled(len, "") |
|||
var temp = List.filled(26, "") |
|||
for (i in 0...len) { |
|||
if (showSteps) System.print("%(left) %(right)") |
|||
var index |
|||
if (mode == Chao.encrypt) { |
|||
index = right.indexOf(text[i]) |
|||
eText[i] = left[index] |
|||
} else { |
|||
index = left.indexOf(text[i]) |
|||
eText[i] = right[index] |
|||
} |
|||
if (i == len - 1) break |
|||
// permute left |
|||
for (j in index..25) temp[j-index] = left[j] |
|||
for (j in 0...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 = temp.join() |
|||
// permute right |
|||
for (j in index..25) temp[j-index] = right[j] |
|||
for (j in 0...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 = temp.join() |
|||
} |
|||
return eText.join() |
|||
} |
|||
} |
|||
var plainText = "WELLDONEISBETTERTHANWELLSAID" |
|||
System.print("The original plaintext is : %(plainText)") |
|||
System.write("\nThe left and right alphabets after each permutation ") |
|||
System.print("during encryption are :\n") |
|||
var cipherText = Chao.exec(plainText, Chao.encrypt, true) |
|||
System.print("\nThe ciphertext is : %(cipherText)") |
|||
var plainText2 = Chao.exec(cipherText, Chao.decrypt, false) |
|||
System.print("\nThe recovered plaintext is : %(plainText2)")</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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 |
|||
</pre> |
|||
=={{header|XPL0}}== |
|||
{{trans|C}} |
|||
<syntaxhighlight lang "XPL0">include xpllib; \For StrLen, StrCopy, Print |
|||
func StrChar(Str, C); |
|||
char Str, C; |
|||
[loop [if Str(0) = 0 then return 0; |
|||
if Str(0) = C then return Str; |
|||
Str:= Str+1; |
|||
]; |
|||
]; |
|||
def \CMode\ ENCRYPT, DECRYPT; |
|||
char L_alphabet, R_alphabet; |
|||
proc Chao(In, Out, Mode, Show_steps); |
|||
char In, Out, Mode, Show_steps; |
|||
int Len, I, J, Index; |
|||
char Store, Left(27), Right(27), Temp(27); |
|||
[Len:= StrLen(In); |
|||
StrCopy(Left, L_alphabet); |
|||
StrCopy(Right, R_alphabet); |
|||
Temp(26):= 0; |
|||
for I:= 0 to Len-1 do |
|||
[if Show_steps then Print("%s %s\n", Left, Right); |
|||
if Mode = ENCRYPT then |
|||
[Index:= StrChar(Right, In(I)) - Right; |
|||
Out(I):= Left(Index); |
|||
] |
|||
else [Index:= StrChar(Left, In(I)) - Left; |
|||
Out(I):= Right(Index); |
|||
]; |
|||
if I = Len-1 then return; |
|||
\Permute Left |
|||
for J:= Index to 26-1 do Temp(J-Index):= Left(J); |
|||
for J:= 0 to Index-1 do Temp(26-Index+J):= Left(J); |
|||
Store:= Temp(1); |
|||
for J:= 2 to 14-1 do Temp(J-1):= Temp(J); |
|||
Temp(13):= Store; |
|||
StrCopy(Left, Temp); |
|||
\Permute Right |
|||
for J:= Index to 26-1 do Temp(J-Index):= Right(J); |
|||
for J:= 0 to Index-1 do Temp(26-Index+J):= Right(J); |
|||
Store:= Temp(0); |
|||
for J:= 1 to 26-1 do Temp(J-1):= Temp(J); |
|||
Temp(25):= Store; |
|||
Store:= Temp(2); |
|||
for J:= 3 to 14-1 do Temp(J-1):= Temp(J); |
|||
Temp(13):= Store; |
|||
StrCopy(Right, Temp); |
|||
]; |
|||
]; |
|||
char Plain_text, Cipher_text, Plain_text2; |
|||
[L_alphabet:= "HXUCZVAMDSLKPEFJRIGTWOBNYQ"; |
|||
R_alphabet:= "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
|||
Plain_text:= "WELLDONEISBETTERTHANWELLSAID"; |
|||
Cipher_text:= MAlloc(StrLen(Plain_text) + 1); |
|||
Plain_text2:= MAlloc(StrLen(Plain_text) + 1); |
|||
Print("The original plaintext is : %s\n", Plain_text); |
|||
Print("\nThe left and right alphabets after each permutation during encryption are :\n\n"); |
|||
Chao(Plain_text, Cipher_text, ENCRYPT, true); |
|||
Print("\nThe ciphertext is : %s\n", Cipher_text); |
|||
Chao(Cipher_text, Plain_text2, DECRYPT, false); |
|||
Print("\nThe recovered plaintext is : %s\n", Plain_text2); |
|||
Release(Cipher_text); |
|||
Release(Plain_text2); |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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 |
|||
</pre> |
|||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
{{trans| |
{{trans|Raku}} |
||
< |
<syntaxhighlight lang="zkl">class Chao{ |
||
var [const private] lAlphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ", |
var [const private] lAlphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ", |
||
rAlphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
rAlphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"; |
||
Line 1,892: | Line 4,022: | ||
right.insert(13,right.pop(2)); // rotate [2..13] once |
right.insert(13,right.pop(2)); // rotate [2..13] once |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="zkl">plainText:="WELLDONEISBETTERTHANWELLSAID"; |
||
println("The original plaintext is : ",plainText); |
println("The original plaintext is : ",plainText); |
||
println("\nThe left and right alphabets after each permutation" |
println("\nThe left and right alphabets after each permutation" |
||
Line 1,901: | Line 4,031: | ||
plainText2:=Chao.decode(cipherText); |
plainText2:=Chao.decode(cipherText); |
||
println("\nThe recovered plaintext is : ",plainText2);</ |
println("\nThe recovered plaintext is : ",plainText2);</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre style="height:45ex"> |
<pre style="height:45ex"> |
Latest revision as of 17:24, 10 March 2024
You are encouraged to solve this task according to the task description, using any language you may know.
- 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 M.Rubin in 2010 and there is a C# implementation here.
- Task
Code the algorithm in your language and test that it works with the plaintext 'WELLDONEISBETTERTHANWELLSAID' used in the paper itself.
11l
F correct_case(string)
R string.filter(s -> s.is_alpha()).map(s -> s.uppercase()).join(‘’)
F permu(String alp; num)
R alp[num..]‘’alp[0 .< num]
F rotate_wheels(lalph, ralph, key)
V newin = ralph.index(key)
R (permu(lalph, newin), permu(ralph, newin))
F scramble_wheels(String =lalph, String =ralph)
lalph = lalph[0]‘’lalph[2.<14]‘’lalph[1]‘’lalph[14..]
ralph = ralph[1.<3]‘’ralph[4.<15]‘’ralph[3]‘’ralph[15..]‘’ralph[0]
R (lalph, ralph)
F do_chao(=msg, =lalpha, =ralpha, en = 1B, show = 0B)
msg = correct_case(msg)
V out = ‘’
I show
print(‘=’ * 54)
print((10 * ‘ ’)‘left:’(21 * ‘ ’)‘right: ’)
print(‘=’ * 54)
print(lalpha‘ ’ralpha" \n")
L(l) msg
I en
(lalpha, ralpha) = rotate_wheels(lalpha, ralpha, l)
out ‘’= lalpha[0]
E
(ralpha, lalpha) = rotate_wheels(ralpha, lalpha, l)
out ‘’= ralpha[0]
(lalpha, ralpha) = scramble_wheels(lalpha, ralpha)
I show
print(lalpha‘ ’ralpha)
R out
V lalpha = ‘HXUCZVAMDSLKPEFJRIGTWOBNYQ’
V ralpha = ‘PTLNBQDEOYSFAVZKGJRIHWXUMC’
V msg = ‘WELLDONEISBETTERTHANWELLSAID’
print(‘L: ’lalpha)
print(‘R: ’ralpha)
print(‘I: ’msg)
V o = do_chao(msg, lalpha, ralpha, 1B, 0B)
print(‘O: ’o)
print(‘D: ’do_chao(o, lalpha, ralpha, 0B, 0B))
print()
do_chao(msg, lalpha, ralpha, 1B, 1B)
- Output:
L: HXUCZVAMDSLKPEFJRIGTWOBNYQ R: PTLNBQDEOYSFAVZKGJRIHWXUMC I: WELLDONEISBETTERTHANWELLSAID O: OAHQHCNYNXTSZJRRHJBYHQKSOUJY D: WELLDONEISBETTERTHANWELLSAID ====================================================== left: right: ====================================================== 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 YFJBGMTKWNOQXCHIDVALZRSPUE JIBMESWKYZXUCOPRTLNHFAGVQD
Ada
This solution uses array slices to permute the left and right strings. Use of slices clarifies the looping logic. Ada strings are indexed with the predefined subtype Positive which begins at 1.
with Ada.Text_IO; use Ada.Text_IO;
procedure chao_slices is
type iMode is (Encrypt, Decrypt);
L_Alphabet : String := "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
R_Alphabet : String := "PTLNBQDEOYSFAVZKGJRIHWXUMC";
plaintext : String := "WELLDONEISBETTERTHANWELLSAID";
ciphertext : String (1 .. plaintext'length);
plaintext2 : String (1 .. plaintext'length);
offset : Natural;
function IndexOf (Source : String; Value : Character) return Positive is
Result : Positive;
begin
for I in Source'Range loop
if Source (I) = Value then
Result := I;
exit;
end if;
end loop;
return Result;
end IndexOf;
function Exec
(Text : String; mode : iMode; showsteps : Boolean := False) return String
is
etext : String (Text'First .. Text'Last);
temp : String (1 .. 26);
index : Positive;
store : Character;
left : String := L_Alphabet;
right : String := R_Alphabet;
begin
for I in Text'Range loop
if showsteps then
Put_Line (left & " " & right);
end if;
if mode = Encrypt then
index := IndexOf (Source => right, Value => Text (I));
etext (I) := left (index);
else
index := IndexOf (Source => left, Value => Text (I));
etext (I) := right (index);
end if;
exit when I = Text'Last;
-- permute left
-- The array value permutations are performed using array slices
-- rather than explicit loops
if index > 1 then
offset := 26 - index;
temp (1 .. offset + 1) := left (index .. index + offset);
temp (offset + 2 .. 26) := left (1 .. index - 1);
store := temp (2);
temp (2 .. 13) := temp (3 .. 14);
temp (14) := store;
left := temp;
-- permute right
-- The array value permutations are performed using array slices
-- rather than explicit loops
temp (1 .. offset + 1) := right (index .. index + offset);
temp (offset + 2 .. 26) := right (1 .. index - 1);
store := temp (1);
temp (1 .. 25) := temp (2 .. 26);
temp (26) := store;
store := temp (3);
temp (3 .. 13) := temp (4 .. 14);
temp (14) := store;
right := temp;
end if;
end loop;
return etext;
end Exec;
begin
Put_Line ("The original text is : " & plaintext);
New_Line;
Put_Line
("The left and right alphabets after each permutation during encryption are:");
New_Line;
ciphertext := Exec (plaintext, Encrypt, True);
New_Line;
Put_Line ("The ciphertext is : " & ciphertext);
plaintext2 := Exec (ciphertext, Decrypt);
New_Line;
Put_Line ("The recovered plaintext is : " & plaintext2);
end chao_slices;
- Output:
The original text 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 RBSKWPEYHUFJIDLGMTONQXCVAZ RYFWZXUCPTLNIHMSAVKGQDJOBE UJIDLGMTONQXCFVAZRBSKWPEYH LNHMSAVKGQDJOIBERYFWZXUCPT ILGMTONQXCFVADZRBSKWPEYHUJ MSVKGQDJOIBERAYFWZXUCPTLNH DRBSKWPEYHUJIZLGMTONQXCFVA YFZXUCPTLNHMSWVKGQDJOIBERA HJIZLGMTONQXCUFVADRBSKWPEY HMWVKGQDJOIBESRAYFZXUCPTLN ILGMTONQXCUFVZADRBSKWPEYHJ VKQDJOIBESRAYGFZXUCPTLNHMW XUFVZADRBSKWPCEYHJILGMTONQ SRYGFZXUCPTLNAHMWVKQDJOIBE WCEYHJILGMTONPQXUFVZADRBSK NAMWVKQDJOIBEHSRYGFZXUCPTL KCEYHJILGMTONWPQXUFVZADRBS NAWVKQDJOIBEHMSRYGFZXUCPTL PXUFVZADRBSKCQEYHJILGMTONW RYFZXUCPTLNAWGVKQDJOIBEHMS KQEYHJILGMTONCWPXUFVZADRBS WGKQDJOIBEHMSVRYFZXUCPTLNA LMTONCWPXUFVZGADRBSKQEYHJI BEMSVRYFZXUCPHTLNAWGKQDJOI The ciphertext is : OAHQHCNYNXTSZJRRUIDHIXWKPKLY The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID
AppleScript
-- Chaocipher algorithm by J.F.Byrne 1918.
on chaocipher(input, |key|, mode)
-- input: text to be enciphered or deciphered.
-- |key|: script object or record with leftAlpha and rightAlpha properties, each of whose values is a shuffled alphabet text.
-- mode: the text "encipher" or "decipher".
script o
property inputChars : input's characters
property leftAlpha : |key|'s leftAlpha's characters
property rightAlpha : |key|'s rightAlpha's characters
property inAlpha : leftAlpha
property outAlpha : rightAlpha
property output : {}
end script
set alphaLen to (count o's leftAlpha)
if ((count o's rightAlpha) ≠ alphaLen) then error
if (mode is "encipher") then
set {o's inAlpha, o's outAlpha} to {o's rightAlpha, o's leftAlpha}
else if (mode is not "decipher") then
error
end if
set zenith to 1
set nadir to alphaLen div 2 + 1
repeat with char in o's inputChars
set char to char's contents
set found to false
repeat with i from 1 to alphaLen
if (o's inAlpha's item i = char) then
set end of o's output to o's outAlpha's item i
set found to true
exit repeat
end if
end repeat
if (found) then
rotate(o's leftAlpha, zenith, alphaLen, -(i - zenith))
rotate(o's leftAlpha, zenith + 1, nadir, -1)
rotate(o's rightAlpha, zenith, alphaLen, -i)
rotate(o's rightAlpha, zenith + 2, nadir, -1)
end if
end repeat
return join(o's output, "")
end chaocipher
on rotate(theList, l, r, amount)
set listLength to (count theList)
if (listLength < 2) then return
if (l < 0) then set l to listLength + l + 1
if (r < 0) then set r to listLength + r + 1
if (l > r) then set {l, r} to {r, l}
script o
property lst : theList
property storage : missing value
end script
set rangeLength to r - l + 1
set amount to (rangeLength + rangeLength - amount) mod rangeLength
if (amount is 0) then return
set o's storage to o's lst's items l thru (l + amount - 1)
repeat with i from (l + amount) to r
set o's lst's item (i - amount) to o's lst's item i
end repeat
set j to r - amount
repeat with i from 1 to amount
set o's lst's item (j + i) to o's storage's item i
end repeat
end rotate
on join(lst, delim)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to delim
set txt to lst as text
set AppleScript's text item delimiters to astid
return txt
end join
-- Return a script object containing a couple of randomised alphabets to use as a choacipher key.
on makeKey()
set lAlpha to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"'s characters
copy lAlpha to rAlpha
script |key|
property leftAlpha : join(shuffle(lAlpha, 1, -1), "")
property rightAlpha : join(shuffle(rAlpha, 1, -1), "")
end script
return |key|
end makeKey
-- Fisher-Yates (aka Durstenfeld, aka Knuth) shuffle.
on shuffle(theList, l, r)
set listLength to (count theList)
if (listLength < 2) then return array
if (l < 0) then set l to listLength + l + 1
if (r < 0) then set r to listLength + r + 1
if (l > r) then set {l, r} to {r, l}
script o
property lst : theList
end script
repeat with i from l to (r - 1)
set j to (random number from i to r)
set v to o's lst's item i
set o's lst's item i to o's lst's item j
set o's lst's item j to v
end repeat
return theList
end shuffle
-- Demo using the two-alphabet key from the Rubin paper and another generated at random.
-- Decription must be with the key that was used for the encription.
on demo(originalText)
set key1 to {leftAlpha:"HXUCZVAMDSLKPEFJRIGTWOBNYQ", rightAlpha:"PTLNBQDEOYSFAVZKGJRIHWXUMC"}
set key2 to makeKey()
set enciphered to chaocipher(originalText, key1, "encipher")
set doubleEnciphered to chaocipher(enciphered, key2, "encipher")
set deDoubleEnciphered to chaocipher(doubleEnciphered, key2, "decipher")
set deciphered to chaocipher(deDoubleEnciphered, key1, "decipher")
return join({"Original text = " & originalText, ¬
"Enciphered = " & enciphered, "Double enciphered = " & doubleEnciphered, ¬
"De-double enciphered = " & deDoubleEnciphered, "Deciphered = " & deciphered}, linefeed)
end demo
demo("WELLDONEISBETTERTHANWELLSAID")
- Output:
"Original text = WELLDONEISBETTERTHANWELLSAID
Enciphered = OAHQHCNYNXTSZJRRHJBYHQKSOUJY
Double enciphered = ZJVDGIXNNDNRHAXQUUJZGAFTANHW
De-double enciphered = OAHQHCNYNXTSZJRRHJBYHQKSOUJY
Deciphered = WELLDONEISBETTERTHANWELLSAID"
Arc
(= lshift '((0 1) (2 14) (1 2) (14 26)))
(= rshift '((1 3) (4 15) (3 4) (15 26) (0 1)))
(= rot (fn (alpha shift)
(let shift (mod shift 26)
(string (cut alpha shift) (cut alpha 0 shift)))))
(= scramble-wheel (fn (alpha moves)
(= oput '())
(up i 0 (- (len moves) 1)
(push (cut alpha ((moves i) 0) ((moves i) 1)) oput))
(= oput (string (rev oput)))))
(= chaocipher (fn (left right msg (o crypted) (o dec?))
(unless crypted
(prn "Encoding " msg " with chaocipher")
(prn left " " right))
(when dec? (swap left right))
(= offset ((positions (msg 0) right) 0))
(= left (rot left offset))
(= right (rot right offset))
(push (cut left 0 1) crypted)
(when dec? (swap left right))
(prn (scramble-wheel left lshift)
" " (scramble-wheel right rshift))
(if (> (len msg) 1)
(chaocipher (scramble-wheel left lshift)
(scramble-wheel right rshift)
(cut msg 1) crypted dec?)
(string (rev crypted)))))
(chaocipher "HXUCZVAMDSLKPEFJRIGTWOBNYQ" "PTLNBQDEOYSFAVZKGJRIHWXUMC"
"WELLDONEISBETTERTHANWELLSAID")
(chaocipher "HXUCZVAMDSLKPEFJRIGTWOBNYQ" "PTLNBQDEOYSFAVZKGJRIHWXUMC"
"OAHQHCNYNXTSZJRRHJBYHQKSOUJY" nil 1)
- Output:
arc> (chaocipher "HXUCZVAMDSLKPEFJRIGTWOBNYQ" "PTLNBQDEOYSFAVZKGJRIHWXUMC"
"WELLDONEISBETTERTHANWELLSAID")
Encoding WELLDONEISBETTERTHANWELLSAID with chaocipher
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
YFJBGMTKWNOQXCHIDVALZRSPUE JIBMESWKYZXUCOPRTLNHFAGVQD
"OAHQHCNYNXTSZJRRHJBYHQKSOUJY"
AutoHotkey
LeftW := "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
RghtW := "PTLNBQDEOYSFAVZKGJRIHWXUMC"
PlainText := "WELLDONEISBETTERTHANWELLSAID"
CipherText := Chao_Cipher(PlainText, LeftW, RghtW) ; "OAHQHCNYNXTSZJRRHJBYHQKSOUJY"
DecipherText:= Chao_Decipher(CipherText, LeftW, RghtW) ; "WELLDONEISBETTERTHANWELLSAID"
MsgBox % Result := "Original text:`t" PlainText "`nCipher text:`t" CipherText "`nDecipher text:`t" DecipherText
return
;-------------------------------------------
Chao_Cipher(PT, LeftW, RghtW){
oRght:=StrSplit(RghtW), oLeft:=StrSplit(LeftW)
for i, p in StrSplit(PT){
result .= (c := Key2Val(oRght, oLeft, p))
oLeft:=Permute(oLeft, c, 1)
oRght:=Permute(oRght, p)
}
return result
}
;-------------------------------------------
Chao_Decipher(CT, LeftW, RghtW){
oRght:=StrSplit(RghtW), oLeft:=StrSplit(LeftW)
for i, c in StrSplit(CT){
result .= (p := Key2Val(oLeft, oRght, c))
oLeft:=Permute(oLeft, c, 1)
oRght:=Permute(oRght, p)
}
return result
}
;-------------------------------------------
Key2Val(Key, Val, char){
for i, ch in Key
if (ch = char)
return Val[i]
}
;-------------------------------------------
Permute(Arr, ch, dt:=0){
for i, c in Arr
if (c=ch)
break
loop % i-dt
Arr.Push(Arr.RemoveAt(1)) ; shift left
ch := Arr[3-dt] ; save 2nd/3rd chr
loop % 11+dt
Arr[A_Index+2-dt]:=Arr[A_Index+3-dt] ; shift pos 3/4-14 left
Arr[14] := ch ; place 2nd/3rd chr in pos 14
return Arr
}
- Output:
Original text: WELLDONEISBETTERTHANWELLSAID Cipher text: OAHQHCNYNXTSZJRRHJBYHQKSOUJY Decipher text: WELLDONEISBETTERTHANWELLSAID
BASIC
' Caocipher Example
' Rosetta Code
' This code was made in Power Basic 3.5 for DOS
CLS
' Left Alphabet
Function AlphaLeft(ct as String, pt as String, CharPos as Integer) as String
Dim tStr as String: tStr=ct
' 1. Shift the entire left alphabet cyclically so the ciphertext letter
' just enciphered is positioned at the zenith (i.e., position 1).
tStr=Right$(ct, Len(ct)-CharPos+1)+Left$(ct, CharPos-1)
' 2. Extract the letter found at position zenith+1 (i.e., the letter to
' the right of the zenith), taking it out of the alphabet, temporarily
' leaving an unfilled "hole"
Dim Hole as String: Hole=Mid$(tStr, 2, 1): Mid$(tStr, 2, 1)=" "
' 3. Shift all letters in positions zenith+2 up to, and including, the
' nadir (zenith+13), moving them one position to the left
tStr=Left$(tStr, 1)+Mid$(tStr, 3, 12)+" "+Right$(tStr, 12)
' 4. Insert the just-extracted letter into the nadir position
' (i.e., zenith+13)
Mid$(tStr, 14, 1)=Hole
AlphaLeft=tStr
End Function
' Right Alphabet
Function AlphaRight(ct as String, pt as String, CharPos as Integer) as String
Dim tStr as String: tStr=pt
' 1. Shift the entire right alphabet cyclically so the plaintext letter
' just enciphered is positioned at the zenith.
tStr=Right$(tStr, Len(tStr)-CharPos+1)+Left$(tStr, CharPos-1)
' 2. Now shift the entire alphabet one more position to the left (i.e.,
' the leftmost letter moves cyclically to the far right), moving a new
' letter into the zenith position.
tStr=Right$(tStr, 25)+Left$(tStr, 1)
' 3. Extract the letter at position zenith+2, taking it out of the
' alphabet, temporarily leaving an unfilled "hole".
Dim Hole as String: Hole=Mid$(tStr, 3, 1): Mid$(tStr, 3, 1)=" ":
' 4. Shift all letters beginning with zenith+3 up to, and including, the
' nadir (zenith+13), moving them one position to the left.
tStr=Left$(tStr, 2)+Mid$(tStr, 4, 11)+" "+Right$(tStr, 12)
' 5. Insert the just-extracted letter into the nadir position (zenith+13)
Mid$(tStr, 14, 1)=Hole
AlphaRight=tStr
End Function
Function Encode(Text as String, ct as String, pt as String) as String
Dim t as Integer
Dim tStr as String: tStr=""
For t=1 to Len(Text)
Dim Char as String: Char=Mid$(Text, t, 1)
Dim CharPos as Integer: CharPos=Instr(pt, Char)
ct=AlphaLeft(ct, pt, CharPos)
pt=AlphaRight(ct, pt, CharPos)
tStr=tStr+Left$(ct, 1)
Next
Encode=tStr
End Function
' Deciphering a Chaocipher-encrypted message is identical to the steps used
' for enciphering. The sole difference is that the decipherer locates the
' known ciphertext letter in the left (ct) alphabet, with the plaintext
' letter being the corresponding letter in the right (pt) alphabet
'
' Alphabet permuting is identical in enciphering and deciphering
Function Decode(Text as String, ct as String, pt as String) as String
Dim t as Integer
Dim tStr as String: tStr=""
For t=1 to Len(Text)
Dim Char as String: Char=Mid$(Text, t, 1)
Dim CharPos as Integer: CharPos=Instr(ct, Char)
ct=AlphaLeft(ct, pt, CharPos)
pt=AlphaRight(ct, pt, CharPos)
tStr=tStr+Right$(pt, 1)
Next
Decode=tStr
End Function
' Start of Main Code
' LEFT (Cipher Text): HXUCZVAMDSLKPEFJRIGTWOBNYQ
Dim tLeft as String: tLeft="HXUCZVAMDSLKPEFJRIGTWOBNYQ"
' RIGHT (Plain Text): PTLNBQDEOYSFAVZKGJRIHWXUMC
Dim tRight as String: tRight="PTLNBQDEOYSFAVZKGJRIHWXUMC"
' Cipher Message (Used to verify a good encoding)
Dim cText as String: cText="OAHQHCNYNXTSZJRRHJBYHQKSOUJY"
' Plain Text Message
Dim pText as String: pText="WELLDONEISBETTERTHANWELLSAID"
Print " Plain Text: "; pText: Print
Dim ctLeft as String: ctLeft=tLeft
Dim ptRight as String: ptRight=tRight
' Final Cipher Text
Dim eText as String: eText=Encode(pText, ctLeft, ptRight)
Print " Cipher Text: "; eText: Print
If eText=cText then Print "Successful" else Print "Failed"
ctLeft=tLeft: ptRight=tRight
Dim dText as String: dText=Decode(eText, ctLeft, ptRight)
Print: Print " Plain Text: "; dText: Print
If dText=pText then Print "Successful" else Print "Failed"
Plain Text: WELLDONEISBETTERTHANWELLSAID Cipher text: OAHQHCNYNXTSZJRRHJBYHQKSOUJY Successful Plain Text: WELLDONEISBETTERTHANWELLSAID Successful
C
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
typedef int bool;
typedef enum { ENCRYPT, DECRYPT } cmode;
const char *l_alphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
const char *r_alphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC";
void chao(const char *in, char *out, cmode mode, bool show_steps) {
int i, j, index;
char store;
size_t len = strlen(in);
char left[27], right[27], temp[27];
strcpy(left, l_alphabet);
strcpy(right, r_alphabet);
temp[26] = '\0';
for (i = 0; i < len; ++i ) {
if (show_steps) printf("%s %s\n", left, right);
if (mode == ENCRYPT) {
index = strchr(right, in[i]) - right;
out[i] = left[index];
}
else {
index = strchr(left, in[i]) - left;
out[i] = right[index];
}
if (i == len - 1) break;
/* permute left */
for (j = index; j < 26; ++j) temp[j - index] = left[j];
for (j = 0; j < index; ++j) temp[26 - index + j] = left[j];
store = temp[1];
for (j = 2; j < 14; ++j) temp[j - 1] = temp[j];
temp[13] = store;
strcpy(left, temp);
/* permute right */
for (j = index; j < 26; ++j) temp[j - index] = right[j];
for (j = 0; j < index; ++j) temp[26 - index + j] = right[j];
store = temp[0];
for (j = 1; j < 26; ++j) temp[j - 1] = temp[j];
temp[25] = store;
store = temp[2];
for (j = 3; j < 14; ++j) temp[j - 1] = temp[j];
temp[13] = store;
strcpy(right, temp);
}
}
int main() {
const char *plain_text = "WELLDONEISBETTERTHANWELLSAID";
char *cipher_text = malloc(strlen(plain_text) + 1);
char *plain_text2 = malloc(strlen(plain_text) + 1);
printf("The original plaintext is : %s\n", plain_text);
printf("\nThe left and right alphabets after each permutation"
" during encryption are :\n\n");
chao(plain_text, cipher_text, ENCRYPT, TRUE);
printf("\nThe ciphertext is : %s\n", cipher_text);
chao(cipher_text, plain_text2, DECRYPT, FALSE);
printf("\nThe recovered plaintext is : %s\n", plain_text2);
free(cipher_text);
free(plain_text2);
return 0;
}
- 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
C#
using System;
namespace Chaocipher {
enum Mode {
ENCRYPT,
DECRYPT,
}
class Program {
const string L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
const string R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC";
static string Exec(string text, Mode mode, bool showSteps = false) {
char[] left = L_ALPHABET.ToCharArray();
char[] right = R_ALPHABET.ToCharArray();
char[] eText = new char[text.Length];
char[] temp = new char[26];
for (int i = 0; i < text.Length; ++i) {
if (showSteps) Console.WriteLine("{0} {1}", string.Join("", left), string.Join("", right));
int index = 0;
if (mode == Mode.ENCRYPT) {
index = Array.IndexOf(right, text[i]);
eText[i] = left[index];
} else {
index = Array.IndexOf(left, text[i]);
eText[i] = right[index];
}
if (i == text.Length - 1) break;
// permute left
for (int j = index; j < 26; ++j) temp[j - index] = left[j];
for (int j = 0; j < index; ++j) temp[26 - index + j] = left[j];
var store = temp[1];
for (int j = 2; j < 14; ++j) temp[j - 1] = temp[j];
temp[13] = store;
temp.CopyTo(left, 0);
// permute right
for (int j = index; j < 26; ++j) temp[j - index] = right[j];
for (int j = 0; j < index; ++j) temp[26 - index + j] = right[j];
store = temp[0];
for (int j = 1; j < 26; ++j) temp[j - 1] = temp[j];
temp[25] = store;
store = temp[2];
for (int j = 3; j < 14; ++j) temp[j - 1] = temp[j];
temp[13] = store;
temp.CopyTo(right, 0);
}
return new string(eText);
}
static void Main(string[] args) {
var plainText = "WELLDONEISBETTERTHANWELLSAID";
Console.WriteLine("The original plaintext is : {0}", plainText);
Console.WriteLine("\nThe left and right alphabets after each permutation during encryption are :\n");
var cipherText = Exec(plainText, Mode.ENCRYPT, true);
Console.WriteLine("\nThe ciphertext is : {0}", cipherText);
var plainText2 = Exec(cipherText, Mode.DECRYPT);
Console.WriteLine("\nThe recovered plaintext is : {0}", plainText2);
}
}
}
- 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
C++
#include <iostream>
enum class Mode {
ENCRYPT,
DECRYPT,
};
const std::string L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
const std::string R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC";
std::string exec(std::string text, Mode mode, bool showSteps = false) {
auto left = L_ALPHABET;
auto right = R_ALPHABET;
auto eText = new char[text.size() + 1];
auto temp = new char[27];
memset(eText, 0, text.size() + 1);
memset(temp, 0, 27);
for (size_t i = 0; i < text.size(); i++) {
if (showSteps) std::cout << left << ' ' << right << '\n';
size_t index;
if (mode == Mode::ENCRYPT) {
index = right.find(text[i]);
eText[i] = left[index];
} else {
index = left.find(text[i]);
eText[i] = right[index];
}
if (i == text.size() - 1) break;
// permute left
for (int j = index; j < 26; ++j) temp[j - index] = left[j];
for (int j = 0; j < index; ++j) temp[26 - index + j] = left[j];
auto store = temp[1];
for (int j = 2; j < 14; ++j) temp[j - 1] = temp[j];
temp[13] = store;
left = temp;
// permurte right
for (int j = index; j < 26; ++j) temp[j - index] = right[j];
for (int j = 0; j < index; ++j) temp[26 - index + j] = right[j];
store = temp[0];
for (int j = 1; j < 26; ++j) temp[j - 1] = temp[j];
temp[25] = store;
store = temp[2];
for (int j = 3; j < 14; ++j) temp[j - 1] = temp[j];
temp[13] = store;
right = temp;
}
return eText;
}
int main() {
auto plainText = "WELLDONEISBETTERTHANWELLSAID";
std::cout << "The original plaintext is : " << plainText << "\n\n";
std::cout << "The left and right alphabets after each permutation during encryption are :\n";
auto cipherText = exec(plainText, Mode::ENCRYPT, true);
std::cout << "\nThe ciphertext is : " << cipherText << '\n';
auto plainText2 = exec(cipherText, Mode::DECRYPT);
std::cout << "\nThe recovered plaintext is : " << plainText2 << '\n';
return 0;
}
- 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
D
import std.stdio;
import std.string;
immutable L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
immutable R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC";
enum Mode {
ENCRYPT,
DECRYPT,
}
string exec(string text, Mode mode, bool showSteps = false) {
char[] left = L_ALPHABET.dup;
char[] right = R_ALPHABET.dup;
char[] eText;
eText.length = text.length;
char[26] temp;
foreach (i; 0..text.length) {
if (showSteps) writeln(left, ' ', right);
int index;
if (mode == Mode.ENCRYPT) {
index = right.indexOf(text[i]);
eText[i] = left[index];
} else {
index = left.indexOf(text[i]);
eText[i] = right[index];
}
if (i == text.length - 1) break;
// permute left
foreach (j; index..26) temp[j - index] = left[j];
foreach (j; 0..index) temp[26 - index + j] = left[j];
auto store = temp[1];
foreach (j; 2..14) temp[j - 1] = temp[j];
temp[13] = store;
left = temp.dup;
// permute right
foreach (j; index..26) temp[j - index] = right[j];
foreach (j; 0..index) temp[26 - index + j] = right[j];
store = temp[0];
foreach (j; 1..26) temp[j - 1] = temp[j];
temp[25] = store;
store = temp[2];
foreach (j; 3..14) temp[j - 1] = temp[j];
temp[13] = store;
right = temp.dup;
}
return eText.idup;
}
void main() {
auto plainText = "WELLDONEISBETTERTHANWELLSAID";
writeln("The original plaintext is : ", plainText);
writeln("\nThe left and right alphabets after each permutation during encryption are :\n");
auto cipherText = exec(plainText, Mode.ENCRYPT, true);
writeln("\nThe ciphertext is : ", cipherText);
auto plainText2 = exec(cipherText, Mode.DECRYPT);
writeln("\nThe recovered plaintext is : ", plainText2);
}
- 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
Delphi
program Chaocipher;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
TMode = (mcEncrypt, mcDecrypt);
const
lAlphabet = 'HXUCZVAMDSLKPEFJRIGTWOBNYQ';
rAlphabet = 'PTLNBQDEOYSFAVZKGJRIHWXUMC';
function Chao(text: AnsiString; Mode: TMode; showSteps: boolean): AnsiString;
begin
var len := Length(text);
var left: AnsiString := lAlphabet;
var right: AnsiString := rAlphabet;
var eText: AnsiString;
SetLength(eText, len);
var temp: AnsiString;
SetLength(temp, 26);
for var i := 0 to len - 1 do
begin
if showSteps then
writeln(left, ' ', right);
var index := 0;
if Mode = mcEncrypt then
begin
index := pos(text[i + 1], right) - 1;
eText[i + 1] := left[index + 1];
end
else
begin
index := pos(text[i + 1], left) - 1;
eText[i + 1] := right[index + 1];
end;
if i = len - 1 then
Break;
// premute left
for var j := index to 25 do
temp[j - index + 1] := left[j + 1];
for var j := 0 to index - 1 do
temp[27 - index + j] := left[j + 1];
var store := temp[2];
for var j := 2 to 13 do
temp[j] := temp[j + 1];
temp[14] := store;
left := temp;
// permute right
for var j := index to 25 do
temp[j - index + 1] := right[j + 1];
for var j := 0 to index - 1 do
temp[27 - index + j] := right[j + 1];
store := temp[0 + 1];
for var j := 1 to 25 do
temp[j] := temp[j + 1];
temp[26] := store;
store := temp[3];
for var j := 3 to 13 do
temp[j] := temp[j + 1];
temp[14] := store;
right := temp;
end;
Result := eText;
end;
begin
var plainText := 'WELLDONEISBETTERTHANWELLSAID';
writeln('The original plaintext is :', plainText);
write(#10'The left and right alphabets after each permutation ');
writeln('during encryption are :'#10);
var cipherText := Chao(plainText, mcEncrypt, true);
writeln(#10'The ciphertext is :', cipherText);
var plainText2 := Chao(cipherText, mcDecrypt, false);
writeln(#10'The recovered plaintext is : ', plainText2);
readln;
end.
EasyLang
proc index c$ . a$[] ind .
for ind = 1 to len a$[]
if a$[ind] = c$
return
.
.
ind = 0
.
left$ = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
right$ = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
#
func$ chao txt$ mode .
left$[] = strchars left$
right$[] = strchars right$
len tmp$[] 26
for c$ in strchars txt$
# print strjoin left$[] & " " & strjoin right$[]
if mode = 1
index c$ right$[] ind
if ind = 0
return ""
.
r$ &= left$[ind]
else
index c$ left$[] ind
if ind = 0
print c$
return ""
.
r$ &= right$[ind]
.
# permute left
for j = ind to 26
tmp$[j - ind + 1] = left$[j]
.
for j = 1 to ind - 1
tmp$[26 - ind + j + 1] = left$[j]
.
h$ = tmp$[2]
for j = 3 to 14
tmp$[j - 1] = tmp$[j]
.
tmp$[14] = h$
swap tmp$[] left$[]
#
# permute right
for j = ind to 26
tmp$[j - ind + 1] = right$[j]
.
for j = 1 to ind - 1
tmp$[26 - ind + j + 1] = right$[j]
.
h$ = tmp$[1]
for j = 2 to 26
tmp$[j - 1] = tmp$[j]
.
tmp$[26] = h$
h$ = tmp$[3]
for j = 4 to 14
tmp$[j - 1] = tmp$[j]
.
tmp$[14] = h$
swap tmp$[] right$[]
.
return r$
.
h$ = chao "WELLDONEISBETTERTHANWELLSAID" 1
print h$
print chao h$ 2
- Output:
OAHQHCNYNXTSZJRRHJBYHQKSOUJY WELLDONEISBETTERTHANWELLSAID
EMal
type Chaocipher:Mode
enum
int ENCRYPT, DECRYPT
end
type Chaocipher
text L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
text R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
fun exec = text by text value, Chaocipher:Mode mode, logic showSteps
^|since texts are mutable, we can operate directly on them without the need of Lists|^
text left = *L_ALPHABET # by using the valueOf operator we are sure that the string is copied
text right = *R_ALPHABET
text eText = text(" ", value.length)
text temp = text(" ", 26)
for int i = 0; i < value.length; ++i
if showSteps do writeLine(left + " " + right) end
int index = 0
if mode == Chaocipher:Mode.ENCRYPT
index = right.find(value[i])
eText[i] = left[index]
else
index = left.find(value[i])
eText[i] = right[index]
end
if i == value.length - 1 do break end
# permute left
for int j = index; j < 26; ++j do temp[j - index] = left[j] end
for int j = 0; j < index; ++j do temp[26 - index + j] = left[j] end
var store = temp[1]
for int j = 2; j < 14; ++j do temp[j - 1] = temp[j] end
temp[13] = store
left = *temp
# permute right
for int j = index; j < 26; ++j do temp[j - index] = right[j] end
for int j = 0; j < index; ++j do temp[26 - index + j] = right[j] end
store = temp[0]
for int j = 1; j < 26; ++j do temp[j - 1] = temp[j] end
temp[25] = store
store = temp[2]
for int j = 3; j < 14; ++j do temp[j - 1] = temp[j] end
temp[13] = store
right = *temp
end
return eText
end
var plainText = "WELLDONEISBETTERTHANWELLSAID"
writeLine("The original plaintext is : " + plainText)
writeLine(EOL + "The left and right alphabets after each permutation during encryption are :" + EOL)
var cipherText = exec(plainText, Chaocipher:Mode.ENCRYPT, true)
writeLine(EOL + "The ciphertext is : " + cipherText)
var plainText2 = exec(cipherText, Chaocipher:Mode.DECRYPT, false)
writeLine(EOL + "The recovered plaintext is : " + plainText2)
- 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
F#
The Functions
// Implement Chaocipher. Nigel Galloway: July 13th., 2019
let pL n=function g when g=n->0 |g when g=(n+1)%26->13 |g->let x=(25+g-n)%26 in if x<13 then x else x+1
let pR n=function g when g=n->25 |g when g=(n+3)%26->13 |g when g=(n+1)%26->0 |g when g=(n+2)%26->1 |g->let x=(24+g-n)%26 in if x<13 then x else x+1
let encrypt lW rW txt=Array.scan(fun (lW,rW) t->let n=Array.findIndex(fun n->n=t) rW in ((Array.permute(pL n) lW,(Array.permute(pR n) rW))))(lW,rW) txt
|>Array.skip 1|>Array.map(fun(n,_)->n.[0])|>System.String
let decrypt lW rW txt=Array.scan(fun (_,lW,rW) t->let n=Array.findIndex(fun n->n=t) lW in ((Array.item n rW,Array.permute(pL n) lW,(Array.permute(pR n) rW))))('0',lW,rW) txt
|>Array.skip 1|>Array.map(fun(n,_,_)->n)|>System.String
The Task
printfn "%s" (encrypt ("HXUCZVAMDSLKPEFJRIGTWOBNYQ".ToCharArray()) ("PTLNBQDEOYSFAVZKGJRIHWXUMC".ToCharArray()) ("WELLDONEISBETTERTHANWELLSAID".ToCharArray()))
printfn "%s" (decrypt ("HXUCZVAMDSLKPEFJRIGTWOBNYQ".ToCharArray()) ("PTLNBQDEOYSFAVZKGJRIHWXUMC".ToCharArray()) ("OAHQHCNYNXTSZJRRHJBYHQKSOUJY".ToCharArray()))
- Output:
OAHQHCNYNXTSZJRRHJBYHQKSOUJY WELLDONEISBETTERTHANWELLSAID
Factor
USING: arrays combinators fry io kernel locals math namespaces
prettyprint sequences sequences.extras strings ;
IN: rosetta-code.chaocipher
CONSTANT: zenith 0
CONSTANT: nadir 13
SYMBOLS: l-alphabet r-alphabet last-index ;
: init-alphabets ( -- )
"HXUCZVAMDSLKPEFJRIGTWOBNYQ" l-alphabet
"PTLNBQDEOYSFAVZKGJRIHWXUMC" r-alphabet [ set ] 2bi@ ;
: zero-alphabet ( seq -- seq' )
last-index get rotate ;
: 3append ( a b c d -- abcd )
append append append ;
:: permute-l-alphabet ( -- )
l-alphabet get zero-alphabet dup
zenith 1 + swap nth :> extracted-char
{
[ 1 head ]
[ nadir 1 + head 2 tail ]
[ drop extracted-char 1string ]
[ nadir 1 + tail ]
} cleave
3append l-alphabet set ;
:: permute-r-alphabet ( -- )
r-alphabet get zero-alphabet
1 rotate dup
zenith 2 + swap nth :> extracted-char
{
[ 2 head ]
[ nadir 1 + head 3 tail ]
[ drop extracted-char 1string ]
[ nadir 1 + tail ]
} cleave
3append r-alphabet set ;
: encipher-char ( char alpha1 alpha2 -- char' )
'[ _ get index dup last-index set _ get nth ] call ;
: encipher ( str quot -- str' )
[ permute-l-alphabet permute-r-alphabet ] compose map
init-alphabets ; inline
: encrypt ( str -- str' )
[ r-alphabet l-alphabet encipher-char ] encipher ;
: decrypt ( str -- str' )
[ l-alphabet r-alphabet encipher-char ] encipher ;
: main ( -- )
init-alphabets
"WELLDONEISBETTERTHANWELLSAID" encrypt dup decrypt
[ print ] bi@ ;
MAIN: main
- Output:
OAHQHCNYNXTSZJRRHJBYHQKSOUJY WELLDONEISBETTERTHANWELLSAID
Fōrmulæ
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.
Programs in Fōrmulæ are created/edited online in its website.
In this page you can see and run the program(s) related to this task and their results. You can also change either the programs or the parameters they are called with, for experimentation, but remember that these programs were created with the main purpose of showing a clear solution of the task, and they generally lack any kind of validation.
Solution
Test 1. Encryption
Test 2. Decryption
FreeBASIC
The BASIC solution works without any changes.
FutureBasic
begin enum
_encrypt
_decrypt
end enum
local fn chaocipher(orig as str255, action as byte, show as bool) as str255
str255 leftStr, rightStr, out
short i, index
leftStr = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
rightStr = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
orig = ucase$(orig)
out[0] = orig[0]
if show then print:print,"The left and right alphabets during encryption are:":print
for i = 1 to orig[0]
if show then print ,leftStr,,rightStr
if action == _encrypt
index = instr$(0, rightStr, mid$(orig, i, 1))
out[i] = leftStr[index]
else
index = instr$(0, leftStr, mid$(orig, i, 1))
out[i] = rightStr[index]
end if
//leftStr permutation
leftStr = mid$(leftStr, index) + left$(leftStr, index-1)
leftStr = left$(leftStr, 1) + mid$(leftStr, 3, 12) + mid$(leftStr, 2, 1) + mid$(leftStr, 15)
//rightStr permutation
rightStr = mid$(rightStr, index+1) + left$(rightStr, index-1) + mid$(rightStr, index, 1)
rightStr = left$(rightStr, 2) + mid$(rightStr, 4, 11) + mid$(rightStr, 3, 1) + mid$(rightStr, 15)
next
end fn = out
str255 original, encrypted, decrypted
original = "WellDoneIsBetterThanWellSaid"
window 1, @"Chaocipher", ( 0, 0, 475, 550 )
print : print ,"The original text is: """; original; """"
encrypted = fn chaocipher(original, _encrypt, yes)
print : print ,"The encrypted text is: """; encrypted; """"
decrypted = fn chaocipher(encrypted, _decrypt, no)
print : print ,"The decrypted text is: """; decrypted; """"
handleevents
- Output:
Go
package main
import(
"fmt"
"strings"
"unicode/utf8"
)
type Mode int
const(
Encrypt Mode = iota
Decrypt
)
const(
lAlphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
rAlphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
)
func Chao(text string, mode Mode, showSteps bool) string {
len := len(text)
if utf8.RuneCountInString(text) != len {
fmt.Println("Text contains non-ASCII characters")
return ""
}
left := lAlphabet
right := rAlphabet
eText := make([]byte, len)
temp := make([]byte, 26)
for i := 0; i < len; i++ {
if showSteps {
fmt.Println(left, " ", right)
}
var index int
if mode == Encrypt {
index = strings.IndexByte(right, text[i])
eText[i] = left[index]
} else {
index = strings.IndexByte(left, text[i])
eText[i] = right[index]
}
if i == len - 1 {
break
}
// permute left
for j := index; j < 26; j++ {
temp[j - index] = left[j]
}
for j := 0; j < index; j++ {
temp[26 - index + j] = left[j]
}
store := temp[1]
for j := 2; j < 14; j++ {
temp[j - 1] = temp[j]
}
temp[13] = store
left = string(temp[:])
// permute right
for j := index; j < 26; j++ {
temp[j - index] = right[j]
}
for j := 0; j < index; j++ {
temp[26 - index + j] = right[j]
}
store = temp[0]
for j := 1; j < 26; j++ {
temp[j - 1] = temp[j]
}
temp[25] = store
store = temp[2]
for j := 3; j < 14; j++ {
temp[j - 1] = temp[j]
}
temp[13] = store
right = string(temp[:])
}
return string(eText[:])
}
func main() {
plainText := "WELLDONEISBETTERTHANWELLSAID"
fmt.Println("The original plaintext is :", plainText)
fmt.Print("\nThe left and right alphabets after each permutation ")
fmt.Println("during encryption are :\n")
cipherText := Chao(plainText, Encrypt, true)
fmt.Println("\nThe ciphertext is :", cipherText)
plainText2 := Chao(cipherText, Decrypt, false)
fmt.Println("\nThe recovered plaintext is :", plainText2)
}
- Output:
Same as Kotlin entry.
Groovy
class Chaocipher {
private enum Mode {
ENCRYPT,
DECRYPT
}
private static final String L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
private static final String R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
private static int indexOf(char[] a, char c) {
for (int i = 0; i < a.length; ++i) {
if (a[i] == c) {
return i
}
}
return -1
}
private static String exec(String text, Mode mode) {
return exec(text, mode, false)
}
private static String exec(String text, Mode mode, Boolean showSteps) {
char[] left = L_ALPHABET.toCharArray()
char[] right = R_ALPHABET.toCharArray()
char[] eText = new char[text.length()]
char[] temp = new char[26]
for (int i = 0; i < text.length(); ++i) {
if (showSteps) {
println("${new String(left)} ${new String(right)}")
}
int index
if (mode == Mode.ENCRYPT) {
index = indexOf(right, text.charAt(i))
eText[i] = left[index]
} else {
index = indexOf(left, text.charAt(i))
eText[i] = right[index]
}
if (i == text.length() - 1) {
break
}
// permute left
if (26 - index >= 0) System.arraycopy(left, index, temp, 0, 26 - index)
System.arraycopy(left, 0, temp, 26 - index, index)
char store = temp[1]
System.arraycopy(temp, 2, temp, 1, 12)
temp[13] = store
left = Arrays.copyOf(temp, temp.length)
// permute right
if (26 - index >= 0) System.arraycopy(right, index, temp, 0, 26 - index)
System.arraycopy(right, 0, temp, 26 - index, index)
store = temp[0]
System.arraycopy(temp, 1, temp, 0, 25)
temp[25] = store
store = temp[2]
System.arraycopy(temp, 3, temp, 2, 11)
temp[13] = store
right = Arrays.copyOf(temp, temp.length)
}
return new String(eText)
}
static void main(String[] args) {
String plainText = "WELLDONEISBETTERTHANWELLSAID"
println("The original plaintext is : $plainText")
println("\nThe left and right alphabets after each permutation during encryption are:")
String cipherText = exec(plainText, Mode.ENCRYPT, true)
println("\nThe cipher text is : $cipherText")
String plainText2 = exec(cipherText, Mode.DECRYPT)
println("\nThe recovered plaintext is : $plainText2")
}
}
- 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 cipher text is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID
Haskell
import Data.List (elemIndex)
chao :: Eq a => [a] -> [a] -> Bool -> [a] -> [a]
chao _ _ _ [] = []
chao l r plain (x : xs) = maybe [] go (elemIndex x src)
where
(src, dst)
| plain = (l, r)
| otherwise = (r, l)
go n =
dst !! n :
chao
(shifted 1 14 (rotated n l))
((shifted 2 14 . shifted 0 26) (rotated n r))
plain
xs
rotated :: Int -> [a] -> [a]
rotated n = take . length <*> drop n . cycle
shifted :: Int -> Int -> [a] -> [a]
shifted src dst s = concat [x, rotated 1 y, b]
where
(a, b) = splitAt dst s
(x, y) = splitAt src a
encode, decode :: Bool
encode = False
decode = True
main :: IO ()
main = do
let chaoWheels =
chao
"HXUCZVAMDSLKPEFJRIGTWOBNYQ"
"PTLNBQDEOYSFAVZKGJRIHWXUMC"
plainText = "WELLDONEISBETTERTHANWELLSAID"
cipherText = chaoWheels encode plainText
mapM_
print
[ plainText,
cipherText,
chaoWheels decode cipherText
]
- Output:
"WELLDONEISBETTERTHANWELLSAID" "OAHQHCNYNXTSZJRRHJBYHQKSOUJY" "WELLDONEISBETTERTHANWELLSAID"
J
reset =: verb define
LEFT =: 'HXUCZVAMDSLKPEFJRIGTWOBNYQ'
RIGHT =: 'PTLNBQDEOYSFAVZKGJRIHWXUMC'
)
enc =: verb define
z =. LEFT {~ i =. RIGHT i. y
permute {. i
z
)
dec =: verb define
z =. RIGHT {~ i =. LEFT i. y
permute {. i
z
)
permute =: verb define
LEFT =: LEFT |.~ - y
LEFT =: (1 |. 13 {. LEFT) , 13 }. LEFT
RIGHT =: RIGHT |.~ - y + 1
RIGHT =: ({. RIGHT) , (1 |. RIGHT {~ 2+i.12) , 13 }. RIGHT
)
chao =: enc :. dec
reset ''
smoutput E =. chao 'WELLDONEISBETTERTHANWELLSAID'
reset ''
smoutput D =. chao^:_1 E
- Output:
OMUUADCMTLZMXXMGXWPCOMUULPTA WELLDONEISBETTERTHANWELLSAID
Java
import java.util.Arrays;
public class Chaocipher {
private enum Mode {
ENCRYPT,
DECRYPT
}
private static final String L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
private static final String R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC";
private static int indexOf(char[] a, char c) {
for (int i = 0; i < a.length; ++i) {
if (a[i] == c) {
return i;
}
}
return -1;
}
private static String exec(String text, Mode mode) {
return exec(text, mode, false);
}
private static String exec(String text, Mode mode, Boolean showSteps) {
char[] left = L_ALPHABET.toCharArray();
char[] right = R_ALPHABET.toCharArray();
char[] eText = new char[text.length()];
char[] temp = new char[26];
for (int i = 0; i < text.length(); ++i) {
if (showSteps) {
System.out.printf("%s %s\n", new String(left), new String(right));
}
int index;
if (mode == Mode.ENCRYPT) {
index = indexOf(right, text.charAt(i));
eText[i] = left[index];
} else {
index = indexOf(left, text.charAt(i));
eText[i] = right[index];
}
if (i == text.length() - 1) {
break;
}
// permute left
if (26 - index >= 0) System.arraycopy(left, index, temp, 0, 26 - index);
System.arraycopy(left, 0, temp, 26 - index, index);
char store = temp[1];
System.arraycopy(temp, 2, temp, 1, 12);
temp[13] = store;
left = Arrays.copyOf(temp, temp.length);
// permute right
if (26 - index >= 0) System.arraycopy(right, index, temp, 0, 26 - index);
System.arraycopy(right, 0, temp, 26 - index, index);
store = temp[0];
System.arraycopy(temp, 1, temp, 0, 25);
temp[25] = store;
store = temp[2];
System.arraycopy(temp, 3, temp, 2, 11);
temp[13] = store;
right = Arrays.copyOf(temp, temp.length);
}
return new String(eText);
}
public static void main(String[] args) {
String plainText = "WELLDONEISBETTERTHANWELLSAID";
System.out.printf("The original plaintext is : %s\n", plainText);
System.out.println("\nThe left and right alphabets after each permutation during encryption are:");
String cipherText = exec(plainText, Mode.ENCRYPT, true);
System.out.printf("\nThe cipher text is : %s\n", cipherText);
String plainText2 = exec(cipherText, Mode.DECRYPT);
System.out.printf("\nThe recovered plaintext is : %s\n", plainText2);
}
}
- 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 cipher text is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID
JavaScript
Script source
const L_ALPHABET = "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
const R_ALPHABET = "PTLNBQDEOYSFAVZKGJRIHWXUMC";
const ENCRYPT = 0;
const DECRYPT = 1;
function setCharAt(str, index, chr) {
if (index > str.length - 1) return str;
return str.substr(0, index) + chr + str.substr(index + 1);
}
function chao(text, mode, show_steps) {
var left = L_ALPHABET;
var right = R_ALPHABET;
var out = text;
var temp = "01234567890123456789012345";
var i = 0;
var index, j, store;
if (show_steps) {
console.log("The left and right alphabets after each permutation during encryption are :");
}
while (i < text.length) {
if (show_steps) {
console.log(left + " " + right);
}
if (mode == ENCRYPT) {
index = right.indexOf(text[i]);
out = setCharAt(out, i, left[index]);
} else {
index = left.indexOf(text[i]);
out = setCharAt(out, i, right[index]);
}
if (i == text.length - 1) {
break;
}
//permute left
j = index;
while (j < 26) {
temp = setCharAt(temp, j - index, left[j])
j += 1;
}
j = 0;
while (j < index) {
temp = setCharAt(temp, 26 - index + j, left[j]);
j += 1;
}
store = temp[1];
j = 2;
while (j < 14) {
temp = setCharAt(temp, j - 1, temp[j]);
j += 1;
}
temp = setCharAt(temp, 13, store);
left = temp;
//permute right
j = index;
while (j < 26) {
temp = setCharAt(temp, j - index, right[j]);
j += 1;
}
j = 0;
while (j < index) {
temp = setCharAt(temp, 26 - index + j, right[j]);
j += 1;
}
store = temp[0];
j = 1;
while (j < 26) {
temp = setCharAt(temp, j - 1, temp[j]);
j += 1;
}
temp = setCharAt(temp, 25, store);
store = temp[2];
j = 3;
while (j < 14) {
temp = setCharAt(temp, j - 1, temp[j]);
j += 1;
}
temp = setCharAt(temp, 13, store);
right = temp;
i += 1;
}
return out;
}
function main() {
var out = document.getElementById("content");
const plain_text = "WELLDONEISBETTERTHANWELLSAID";
out.innerHTML = "<p>The original plaintext is : " + plain_text + "</p>";
var cipher_text = chao(plain_text, ENCRYPT, true);
out.innerHTML += "<p>The ciphertext is : " + cipher_text + "</p>";
var decipher_text = chao(cipher_text, DECRYPT, false);
out.innerHTML += "<p>The recovered plaintext is : " + decipher_text + "</p>";
}
Solution page
<!DOCTYPE html>
<html>
<head>
<title>Chaocipher</title>
<script src="chaocipher.js"></script>
</head>
<body onload="main()">
<div id="content"></div>
</body>
</html>
- Output:
The original plaintext is : WELLDONEISBETTERTHANWELLSAID The ciphertext is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID
Julia
Modified from the Kotlin and Raku entries.
const leftalphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
const rightalphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
function chacocoding(text, encoding, verbose=false)
left, right = Vector{Char}(leftalphabet), Vector{Char}(rightalphabet)
len, coded = length(text), similar(Vector{Char}(text))
for i in 1:len
verbose && println(String(left), " ", String(right))
n = indexin(text[i], encoding ? right : left)[1]
coded[i] = encoding ? left[n] : right[n]
if i < len
left .= circshift(left, -n + 1)
left[2:14] .= circshift(left[2:14], -1)
right .= circshift(right, -n)
right[3:14] .= circshift(right[3:14], -1)
end
end
String(coded)
end
function testchacocipher(txt)
println("The original plaintext is: $txt")
println("\nThe left and right alphabets for each character during encryption are:")
encoded = chacocoding(txt, true, true)
println("\nThe encoded ciphertext is: $encoded")
decoded = chacocoding(encoded, false)
println("\nDecoded, the recovered plaintext is: $decoded")
end
testchacocipher("WELLDONEISBETTERTHANWELLSAID")
- Output:
The original plaintext is: WELLDONEISBETTERTHANWELLSAID The left and right alphabets for each character 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 encoded ciphertext is: OAHQHCNYNXTSZJRRHJBYHQKSOUJY Decoded, the recovered plaintext is: WELLDONEISBETTERTHANWELLSAID
Kotlin
This is based on the C# implementation referred to in the task description, except that the encrypt and decrypt operations are combined into a single method.
// Version 1.2.40
enum class Mode { ENCRYPT, DECRYPT }
object Chao {
private val lAlphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
private val rAlphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
fun exec(text: String, mode: Mode, showSteps: Boolean = false): String {
var left = lAlphabet
var right = rAlphabet
val eText = CharArray(text.length)
val temp = CharArray(26)
for (i in 0 until text.length) {
if (showSteps) println("$left $right")
var index: Int
if (mode == Mode.ENCRYPT) {
index = right.indexOf(text[i])
eText[i] = left[index]
}
else {
index = left.indexOf(text[i])
eText[i] = right[index]
}
if (i == text.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(eText)
}
}
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.exec(plainText, Mode.ENCRYPT, true)
println("\nThe ciphertext is : $cipherText")
val plainText2 = Chao.exec(cipherText, Mode.DECRYPT)
println("\nThe recovered plaintext is : $plainText2")
}
- 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
Lua
-- Chaocipher, in Lua, 6/19/2020 db
local Chaocipher = {
ct = "HXUCZVAMDSLKPEFJRIGTWOBNYQ",
pt = "PTLNBQDEOYSFAVZKGJRIHWXUMC",
encrypt = function(self, text) return self:_encdec(text, true) end,
decrypt = function(self, text) return self:_encdec(text, false) end,
_encdec = function(self, text, encflag)
local ct, pt, s = self.ct, self.pt, ""
local cshl = function(s,i) return s:sub(i) .. s:sub(1,i-1) end
local sshl = function(s,i) return s:sub(1,i-1) .. s:sub(i+1,14) .. s:sub(i,i) .. s:sub(15) end
for ch in text:gmatch(".") do
local i = (encflag and pt or ct):find(ch)
s = s .. (encflag and ct or pt):sub(i,i)
if encflag then print(ct, pt, ct:sub(i,i), pt:sub(i,i)) end
ct, pt = sshl(cshl(ct, i), 2), sshl(cshl(pt, i+1), 3)
end
return s
end,
}
local plainText = "WELLDONEISBETTERTHANWELLSAID"
local encryptText = Chaocipher:encrypt(plainText)
local decryptText = Chaocipher:decrypt(encryptText)
print()
print("The original text was: " .. plainText)
print("The encrypted text is: " .. encryptText)
print("The decrypted text is: " .. decryptText)
- Output:
HXUCZVAMDSLKPEFJRIGTWOBNYQ PTLNBQDEOYSFAVZKGJRIHWXUMC O W ONYQHXUCZVAMDBSLKPEFJRIGTW XUCPTLNBQDEOYMSFAVZKGJRIHW A E ADBSLKPEFJRIGMTWONYQHXUCZV OYSFAVZKGJRIHMWXUCPTLNBQDE H L HUCZVADBSLKPEXFJRIGMTWONYQ NBDEOYSFAVZKGQJRIHMWXUCPTL Q L QUCZVADBSLKPEHXFJRIGMTWONY NBEOYSFAVZKGQDJRIHMWXUCPTL H D HFJRIGMTWONYQXUCZVADBSLKPE JRHMWXUCPTLNBIEOYSFAVZKGQD C O CVADBSLKPEHFJZRIGMTWONYQXU YSAVZKGQDJRHMFWXUCPTLNBIEO N N NQXUCVADBSLKPYEHFJZRIGMTWO BIOYSAVZKGQDJERHMFWXUCPTLN Y E YHFJZRIGMTWONEQXUCVADBSLKP RHFWXUCPTLNBIMOYSAVZKGQDJE N I NQXUCVADBSLKPEYHFJZRIGMTWO MOSAVZKGQDJERYHFWXUCPTLNBI X S XCVADBSLKPEYHUFJZRIGMTWONQ AVKGQDJERYHFWZXUCPTLNBIMOS T B TONQXCVADBSLKWPEYHUFJZRIGM IMSAVKGQDJERYOHFWZXUCPTLNB S E SKWPEYHUFJZRILGMTONQXCVADB RYHFWZXUCPTLNOBIMSAVKGQDJE Z T ZILGMTONQXCVARDBSKWPEYHUFJ LNBIMSAVKGQDJOERYHFWZXUCPT J T JILGMTONQXCVAZRDBSKWPEYHUF LNIMSAVKGQDJOBERYHFWZXUCPT R E RBSKWPEYHUFJIDLGMTONQXCVAZ RYFWZXUCPTLNIHMSAVKGQDJOBE R R RSKWPEYHUFJIDBLGMTONQXCVAZ YFZXUCPTLNIHMWSAVKGQDJOBER H T HFJIDBLGMTONQUXCVAZRSKWPEY LNHMWSAVKGQDJIOBERYFZXUCPT J H JDBLGMTONQUXCIVAZRSKWPEYHF MWAVKGQDJIOBESRYFZXUCPTLNH B A BGMTONQUXCIVALZRSKWPEYHFJD VKQDJIOBESRYFGZXUCPTLNHMWA Y N YFJDBGMTONQUXHCIVALZRSKWPE HMAVKQDJIOBESWRYFGZXUCPTLN H W HIVALZRSKWPEYCFJDBGMTONQUX RYGZXUCPTLNHMFAVKQDJIOBESW Q E QXHIVALZRSKWPUEYCFJDBGMTON SWYGZXUCPTLNHRMFAVKQDJIOBE K L KPUEYCFJDBGMTWONQXHIVALZRS NHMFAVKQDJIOBRESWYGZXUCPTL S L SPUEYCFJDBGMTKWONQXHIVALZR NHFAVKQDJIOBRMESWYGZXUCPTL O S OQXHIVALZRSPUNEYCFJDBGMTKW WYZXUCPTLNHFAGVKQDJIOBRMES U A UEYCFJDBGMTKWNOQXHIVALZRSP GVQDJIOBRMESWKYZXUCPTLNHFA J I JBGMTKWNOQXHIDVALZRSPUEYCF OBMESWKYZXUCPRTLNHFAGVQDJI Y D The original text was: WELLDONEISBETTERTHANWELLSAID The encrypted text is: OAHQHCNYNXTSZJRRHJBYHQKSOUJY The decrypted text is: WELLDONEISBETTERTHANWELLSAID
Mathematica/Wolfram Language
ClearAll[ichaoalphabet, iMoveToFront, ChaoCipher]
ichaoalphabet = CharacterRange["A", "Z"];
iMoveToFront[l_List, sel_] := Module[{p},
p = FirstPosition[l, sel];
RotateLeft[l, p - 1]
]
ChaoCipher::wrongcipheralpha =
"The cipher alphabet `1` is not a permutation of \
\"A\"\[LongDash]\"Z\".";
ChaoCipher::wrongplainalpha =
"The plain alphabet `1` is not a permutation of \"A\"\[LongDash]\"Z\
\".";
ChaoCipher[str_String, {plainalpha_List, cipheralpha_List}] :=
Module[{pa, ca, plain, new, papermute, capermute, out},
ca = ToUpperCase[cipheralpha];
pa = ToUpperCase[plainalpha];
If[Sort[ca] =!= Sort[ichaoalphabet],
Message[ChaoCipher::wrongcipheralpha, ca];
$Failed
,
If[Sort[pa] =!= Sort[ichaoalphabet],
Message[ChaoCipher::wrongplainalpha, pa];
$Failed
,
capermute = SubsetMap[RotateLeft, Range[26], Range[2, 14]];
papermute =
SubsetMap[RotateLeft, RotateLeft[Range[26], 1], Range[3, 14]];
plain =
Select[Characters[ToUpperCase[str]], MemberQ[ichaoalphabet, #] &];
out = Table[
new = Association[Thread[pa -> ca]][p];
pa = iMoveToFront[pa, p];
ca = iMoveToFront[ca, new];
pa = pa[[papermute]];
ca = ca[[capermute]];
new
,
{p, plain}
];
StringJoin[out]
]
]
]
ChaoCipher["WELLDONEISBETTERTHANWELLSAID",{Characters@"PTLNBQDEOYSFAVZKGJRIHWXUMC",Characters@"HXUCZVAMDSLKPEFJRIGTWOBNYQ"}]
- Output:
OAHQHCNYNXTSZJRRHJBYHQKSOUJY
Nim
import strformat
type
Mode = enum
Encrypt
Decrypt
const lAlphabet: string = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
const rAlphabet: string = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
proc chao(text: string, mode: Mode, verbose: bool = false): string =
var left = lAlphabet
var right = rAlphabet
var eText = newSeq[char](text.len)
var temp: array[26, char]
for i in 0..<text.len:
if verbose:
echo &"{left} {right}"
var index: int
if mode == Encrypt:
index = right.find(text[i])
eText[i] = left[index]
else:
index = left.find(text[i])
eText[i] = right[index]
if (i == text.len - 1):
break
# permute left
for j in index..25:
temp[j - index] = left[j]
for j in 0..<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 = ""
for i in temp:
left &= $i
# permute right
for j in index..25:
temp[j - index] = right[j]
for j in 0..<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 = ""
for i in temp:
right &= $i
for i in eText:
result &= $i
var plainText = "WELLDONEISBETTERTHANWELLSAID"
echo &"The original plaintext is: {plainText}"
echo "\nThe left and right alphabets after each permutation during encryption are:\n"
var cipherText = chao(plainText, Encrypt, true)
echo &"\nThe ciphertext is: {cipherText}"
var plainText2 = chao(cipherText, Decrypt, false)
echo &"\nThe recovered plaintext is: {plainText2}"
- 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
Another implementation
Using functions from the stdlib instead of manual array manipulations:
import std/[algorithm, strutils]
type
Mode = enum
Encrypt
Decrypt
const
lAlphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
rAlphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
proc chao(text: string; mode: Mode; verbose = false): string =
var
left = lAlphabet
right = rAlphabet
eText = newSeq[char](text.len)
for i in 0 ..< text.len:
if verbose:
echo left, " ", right
var index: int
if mode == Encrypt:
index = right.find(text[i])
eText[i] = left[index]
else:
index = left.find(text[i])
eText[i] = right[index]
if i == text.len - 1:
break
# permute left
left.rotateLeft(index)
left.rotateLeft(1..13, 1)
# permute right
right.rotateLeft(index + 1)
right.rotateLeft(2..13, 1)
result = eText.join()
let plainText = "WELLDONEISBETTERTHANWELLSAID"
echo "The original plaintext is: ", plainText
echo "\nThe left and right alphabets after each permutation during encryption are:\n"
let cipherText = chao(plainText, Encrypt, true)
echo "\nThe ciphertext is: ", cipherText
let plainText2 = chao(cipherText, Decrypt, false)
echo "\nThe recovered plaintext is: ", plainText2
Same output as above.
Objeck
class Chaocipher {
L_ALPHABET : static : Char[];
R_ALPHABET : static : Char[];
function : Main(args : String[]) ~ Nil {
L_ALPHABET := "HXUCZVAMDSLKPEFJRIGTWOBNYQ"->ToCharArray();
R_ALPHABET := "PTLNBQDEOYSFAVZKGJRIHWXUMC"->ToCharArray();
plainText := "WELLDONEISBETTERTHANWELLSAID"->ToCharArray();
System.IO.Console->Print("The original plaintext is: ")->PrintLine(plainText);
"\nThe left and right alphabets after each permutation during encryption are:\n"->PrintLine();
cipherText := Chao(plainText, Mode->ENCRYPT, true);
System.IO.Console->Print("\nThe ciphertext is: ")->PrintLine(cipherText);
plainText2 := Chao(cipherText, Mode->DECRYPT, false);
System.IO.Console->Print("The recovered plaintext is: ")->PrintLine(plainText2);
}
function : Chao(in : Char[], mode : Mode, show_steps : Bool) ~ Char[] {
i : Int; j : Int; index : Int;
store : Char;
len := in->Size();
left := Char->New[26]; right := Char->New[26]; temp := Char->New[26];
eText := Char->New[len];
Runtime->Copy(left, 0, L_ALPHABET, 0, L_ALPHABET->Size());
Runtime->Copy(right, 0, R_ALPHABET, 0, R_ALPHABET->Size());
for(i := 0; i < len; i += 1;) {
if (show_steps) {
System.IO.Console->Print(left)->Print(' ')->PrintLine(right);
};
if (mode = Mode->ENCRYPT) {
index := IndexOf(right, in[i]);
eText[i] := left[index];
}
else {
index := IndexOf(left, in[i]);
eText[i] := right[index];
};
if (i = len - 1) {
break;
};
# left
for(j := index; j < 26; j += 1;) { temp[j - index] := left[j]; };
for(j :=0; j < index; j += 1;) { temp[26 - index + j] := left[j]; };
store := temp[1];
for(j := 2; j < 14; j += 1;) { temp[j - 1] := temp[j]; };
temp[13] := store;
Runtime->Copy(left, 0, temp, 0, temp->Size());
# right
for(j := index; j < 26; j += 1;) { temp[j - index] := right[j]; };
for(j :=0; j < index; j += 1;) { temp[26 - index + j] := right[j]; };
store := temp[0];
for(j :=1; j < 26; j += 1;) { temp[j - 1] := temp[j]; };
temp[25] := store;
store := temp[2];
for(j := 3; j < 14; j += 1;) { temp[j - 1] := temp[j]; };
temp[13] := store;
Runtime->Copy(right, 0, temp, 0, temp->Size());
};
return eText;
}
function : IndexOf(str : Char[], c : Char) ~ Int {
for(i := 0; i < str->Size(); i += 1;) {
if(c = str[i]) {
return i;
};
};
return -1;
}
enum Mode { ENCRYPT, DECRYPT }
}
- 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
Pascal
program chaocipher(input, output);
const
{ This denotes a `set` literal: }
alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
{ The `card` function is an Extended Pascal (ISO 10206) extension. }
alphabetCardinality = card(alphabet);
{ 1st character denotes “zenith”. }
zenith = 1;
{ In a 26-character alphabet the 14th character denotes “nadir”. }
nadir = alphabetCardinality div 2 + 1;
{ For simplicity use compile-time-defined maximum lengths. }
messageMaximumLength = 80;
type
{ This “discriminates” the Extended Pascal schema data type `string` to be }
{ capable of holding strings up to `alphabetCardinality` `char` values. }
map = string(alphabetCardinality);
{ Variables of this data type can only assume integer values within 1..26: }
mapCharacterIndex = 1..alphabetCardinality;
{ Later used as a buffer for the input/output. }
message = string(messageMaximumLength);
messageCharacterIndex = 1..messageMaximumLength;
{ Stores a key for the Chaocipher algorithm. }
key = record
cipherText: map;
plainText: map;
end;
{ --- auxilliary routines ---------------------------------------------- }
{
\brief verifies that a key is valid for the Chaocipher
\param sample a potential `key` for a Chaocipher
\return `true` iff \param sample is an acceptable `key`
}
{ `protected` (Extended Pascal extension) denotes an immutable parameter. }
function isValid(protected sample: key): Boolean;
{ Determines whether a `map` contains all characters of `alphabet`. }
{ Nesting this function allows for a neat expression below. }
function isComplete(protected text: map): Boolean;
var
i: integer;
{ `value []` will initialize this variable to an empty set value. }
{ This is an Extended Pascal (ISO 10206) extension. }
s: set of char value [];
begin
{ NB: In Pascal `for`-loop limits are inclusive. }
for i := 1 to length(text) do
begin
{ This adds the set containing one character to the set `s`. }
s := s + [text[i]]
end;
isComplete := card(s) = alphabetCardinality
end;
begin
{ This way `sample.cipherText` can be simply written as `cipherText`. }
with sample do
begin
{ `and_then` is an EP extension indicating “lazy evaluation”. }
isValid := (alphabetCardinality > 8) and_then
isComplete(cipherText) and_then isComplete(plainText)
end
end;
{
\brief permutes a key for the next encryption/decryption step
\param shift the index of the characters just substituted
}
{ `var` means the parameter value will be modified _at_ the call site. }
procedure permute(var state: key; protected shift: mapCharacterIndex);
begin
with state do
begin
{ Indices in `cipherText[1..pred(shift)]` _must_ be non-descending: }
if shift > 1 then
begin
cipherText := subStr(cipherText, shift) + cipherText[1..pred(shift)]
{ `subStr(str, ini)` is equivalent to `str[ini..length(str)]`. }
end;
{ Likewise, `succ(shift)` must be a valid index in `plainText`: }
if shift < alphabetCardinality then
begin
plainText := subStr(plainText, succ(shift)) + plainText[1..shift]
end;
{ If it does _not_ _alter_ the _entire_ string’s _length_, you can }
{ modify parts of a string like this (Extended Pascal extension): }
cipherText[zenith+1..nadir] := cipherText[zenith+2..nadir] + cipherText[zenith+1];
plainText[zenith+2..nadir] := plainText[zenith+3..nadir] + plainText[zenith+2]
end
end;
{ --- the core routine of the algorithm -------------------------------- }
{
\brief performs Chaocipher common steps
\param line the message to encrypt/decrypt
\param state the initial key to start encrpytion/decryption with
\param locate a function determining the 2-tuple index in the key
\param substitute the procedure substituting the correct characters
}
procedure chaocipher(
var line: message;
var state: key;
{ These are “routine parameters”. Essentially the address of a routine }
{ matching the specified routine signature is passed to `chaocipher`. }
function locate(protected i: messageCharacterIndex): mapCharacterIndex;
procedure substitute(
protected i: messageCharacterIndex;
protected z: mapCharacterIndex
)
);
var
{ For demonstration purposes: In this program }
{ `line.capacity` refers to `messageMaximumLength`. }
i: 1..line.capacity;
substitutionPairIndex: mapCharacterIndex;
begin
{ Don’t trust user input, even though this is just a RosettaCode example. }
if not isValid(state) then
begin
writeLn('Error: Key is invalid. Got:');
writeLn('Cipher text: ', state.cipherText);
writeLn(' Plain text: ', state.plainText);
halt
end;
for i := 1 to length(line) do
begin
{ We’ll better skip characters that aren’t in the `alphabet`. }
if line[i] in alphabet then
begin
{ Here you see the beauty of using routine parameters. }
{ Depending on whether we’re encrypting or decrypting, }
{ you need to find a character in the `cipherText` or }
{ `plainText` key value respectively, yet the basic order
{ of the steps are still the same. }
substitutionPairIndex := locate(i);
substitute(i, substitutionPairIndex);
permute(state, substitutionPairIndex)
end
end
end;
{ --- entry routines --------------------------------------------------- }
{
\brief encrypts a message according to Chaocipher
\param line a message to encrypt
\param state the key to begin with
\return the encrypted message \param line using the provided key
}
{ Note: without `var` or `protected` both `encrypt` and `decrypt`get }
{ and have their own independent copies of the parameter values. }
function encrypt(line: message; state: key): message;
function encryptor(protected i: messageCharacterIndex): mapCharacterIndex;
begin
encryptor := index(state.plainText, line[i])
end;
procedure substitutor(
protected i: messageCharacterIndex;
protected z: mapCharacterIndex
);
begin
line[i] := state.cipherText[z]
end;
begin
chaocipher(line, state, encryptor, substitutor);
encrypt := line
end;
{
\brief decrypts a message according to Chaocipher
\param line the encrypted message
\param state the key to begin with
\return the decrypted message \param line using the provided key
}
function decrypt(line: message; state: key): message;
function decryptor(protected i: messageCharacterIndex): mapCharacterIndex;
begin
decryptor := index(state.cipherText, line[i])
end;
procedure substitutor(
protected i: messageCharacterIndex;
protected z: mapCharacterIndex
);
begin
line[i] := state.plainText[z]
end;
begin
chaocipher(line, state, decryptor, substitutor);
decrypt := line
end;
{ === MAIN ============================================================= }
var
exampleKey: key;
line: message;
begin
{ Instead of writing `exampleKey.cipherText := '…', you can }
{ write in Extended Pascal a `record` literal like this: }
exampleKey := key[
cipherText: 'HXUCZVAMDSLKPEFJRIGTWOBNYQ';
plainText: 'PTLNBQDEOYSFAVZKGJRIHWXUMC';
];
{ `EOF` is shorthand for `EOF(input)`. }
while not EOF do
begin
{ `readLn(line)` is shorthand for `readLn(input, line)`. }
readLn(line);
line := encrypt(line, exampleKey);
writeLn(decrypt(line, exampleKey));
{ Likewise, `writeLn(line)` is short for `writeLn(output, line)`. }
writeLn(line)
end
end.
- Input:
WELLDONEISBETTERTHANWELLSAID
- Output:
WELLDONEISBETTERTHANWELLSAID OAHQHCNYNXTSZJRRHJBYHQKSOUJY
Perl
Since rotate is not a built-in in Perl, using a custom one, not general-purpose but sufficient for this task.
use strict;
use warnings;
my(@left,@right,$e_msg,$d_msg);
sub init {
@left = split '', 'HXUCZVAMDSLKPEFJRIGTWOBNYQ';
@right = split '', 'PTLNBQDEOYSFAVZKGJRIHWXUMC';
}
sub encode {
my($letter) = @_;
my $index = index join('', @right), $letter;
my $enc = $left[$index];
left_permute($index);
right_permute($index);
$enc
}
sub decode {
my($letter) = @_;
my $index = index join('', @left), $letter;
my $dec = $right[$index];
left_permute($index);
right_permute($index);
$dec
}
sub right_permute {
my($index) = @_;
rotate(\@right, $index + 1);
rotate(\@right, 1, 2, 13);
}
sub left_permute {
my($index) = @_;
rotate(\@left, $index);
rotate(\@left, 1, 1, 13);
}
sub rotate {
my @list = @{ shift() };
my($n,$s,$e) = @_;
$s ? @list[0..$s-1, $s+$n..$e+$n-1, $s..$s+$n-1, $e+1..$#list]
: @list[$n..$#list, 0..$n-1]
}
init; $e_msg .= encode $_ for split '', 'WELLDONEISBETTERTHANWELLSAID';
init; $d_msg .= decode $_ for split '', $e_msg;
print "$e_msg\n$d_msg\n";
- Output:
OMUUADCMTLZMXXMGXWPCOMUULPTA WELLDONEISBETTERTHANWELLSAID
Phix
Originally translated from C, but ended up more of a direct implementation of the algorithm in the pdf.
-- demo\rosetta\Chao_cipher.exw with javascript_semantics constant l_alphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ", r_alphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC" enum ENCRYPT, DECRYPT function chao_cipher(string s, integer mode, bool show_steps) integer len = length(s) string out = repeat(' ',len), left = l_alphabet, right = r_alphabet for i=1 to len do if show_steps then printf(1,"%s %s\n", {left, right}) end if integer index = find(s[i],iff(mode==ENCRYPT?right:left)) out[i] = iff(mode==ENCRYPT?left:right)[index] if i==len then exit end if /* permute left */ left = left[index..26]&left[1..index-1] left[2..14] = left[3..14]&left[2] /* permute right */ right = right[index+1..26]&right[1..index] right[3..14] = right[4..14]&right[3] end for return out end function string plain_text = "WELLDONEISBETTERTHANWELLSAID" printf(1,"The original plaintext is : %s\n", {plain_text}) --printf(1,"\nThe left and right alphabets after each permutation"& -- " during encryption are :\n\n") --string cipher_text = chao_cipher(plain_text, ENCRYPT, true) string cipher_text = chao_cipher(plain_text, ENCRYPT, false) printf(1,"\nThe ciphertext is : %s\n", {cipher_text}) string plain_text2 = chao_cipher(cipher_text, DECRYPT, false) printf(1,"\nThe recovered plaintext is : %s\n", {plain_text2})
- Output:
The original plaintext is : WELLDONEISBETTERTHANWELLSAID The ciphertext is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID
Python
Procedural
# Python3 implementation of Chaocipher
# left wheel = ciphertext wheel
# right wheel = plaintext wheel
def main():
# letters only! makealpha(key) helps generate lalpha/ralpha.
lalpha = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
ralpha = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
msg = "WELLDONEISBETTERTHANWELLSAID"
print("L:", lalpha)
print("R:", ralpha)
print("I:", msg)
print("O:", do_chao(msg, lalpha, ralpha, 1, 0), "\n")
do_chao(msg, lalpha, ralpha, 1, 1)
def do_chao(msg, lalpha, ralpha, en=1, show=0):
msg = correct_case(msg)
out = ""
if show:
print("="*54)
print(10*" " + "left:" + 21*" " + "right: ")
print("="*54)
print(lalpha, ralpha, "\n")
for L in msg:
if en:
lalpha, ralpha = rotate_wheels(lalpha, ralpha, L)
out += lalpha[0]
else:
ralpha, lalpha = rotate_wheels(ralpha, lalpha, L)
out += ralpha[0]
lalpha, ralpha = scramble_wheels(lalpha, ralpha)
if show:
print(lalpha, ralpha)
return out
def makealpha(key=""):
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
z = set()
key = [x.upper() for x in (key + alpha[::-1])
if not (x.upper() in z or z.add(x.upper()))]
return "".join(key)
def correct_case(string):
return "".join([s.upper() for s in string if s.isalpha()])
def permu(alp, num):
alp = alp[:num], alp[num:]
return "".join(alp[::-1])
def rotate_wheels(lalph, ralph, key):
newin = ralph.index(key)
return permu(lalph, newin), permu(ralph, newin)
def scramble_wheels(lalph, ralph):
# LEFT = cipher wheel
# Cycle second[1] through nadir[14] forward
lalph = list(lalph)
lalph = "".join([*lalph[0],
*lalph[2:14],
lalph[1],
*lalph[14:]])
# RIGHT = plain wheel
# Send the zenith[0] character to the end[25],
# cycle third[2] through nadir[14] characters forward
ralph = list(ralph)
ralph = "".join([*ralph[1:3],
*ralph[4:15],
ralph[3],
*ralph[15:],
ralph[0]])
return lalph, ralph
main()
L: HXUCZVAMDSLKPEFJRIGTWOBNYQ R: PTLNBQDEOYSFAVZKGJRIHWXUMC I: WELLDONEISBETTERTHANWELLSAID O: OAHQHCNYNXTSZJRRHJBYHQKSOUJY ====================================================== left: right: ====================================================== 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 YFJBGMTKWNOQXCHIDVALZRSPUE JIBMESWKYZXUCOPRTLNHFAGVQD OAHQHCNYNXTSZJRRHJBYHQKSOUJY WELLDONEISBETTERTHANWELLSAID
Functional
'''Chaocipher'''
from itertools import chain, cycle, islice
# chao :: String -> String -> Bool -> String -> String
def chao(l):
'''Chaocipher encoding or decoding for the given
left and right 'wheels'.
A ciphertext is returned if the boolean flag
is True, and a plaintext if the flag is False.
'''
def go(l, r, plain, xxs):
if xxs:
(src, dst) = (l, r) if plain else (r, l)
(x, xs) = (xxs[0], xxs[1:])
def chaoProcess(n):
return [dst[n]] + go(
shifted(1)(14)(rotated(n, l)),
compose(shifted(2)(14))(shifted(0)(26))(
rotated(n, r)
),
plain,
xs
)
return maybe('')(chaoProcess)(
elemIndex(x)(src)
)
else:
return []
return lambda r: lambda plain: lambda xxs: concat(go(
l, r, plain, xxs
))
# rotated :: Int -> [a] -> [a]
def rotated(z, s):
'''Rotation of string s by z characters.'''
return take(len(s))(
drop(z)(
cycle(s)
)
)
# shifted :: Int -> Int -> [a] -> [a]
def shifted(src):
'''The string s with a set of its characters cyclically
shifted from a source index to a destination index.
'''
def go(dst, s):
(a, b) = splitAt(dst)(s)
(x, y) = splitAt(src)(a)
return concat([x, rotated(1, y), b])
return lambda dst: lambda s: go(dst, s)
# TEST ----------------------------------------------------
# main :: IO ()
def main():
'''Print the plain text, followed by
a corresponding cipher text,
and a decode of that cipher text.
'''
chaoWheels = chao(
"HXUCZVAMDSLKPEFJRIGTWOBNYQ"
)(
"PTLNBQDEOYSFAVZKGJRIHWXUMC"
)
plainText = "WELLDONEISBETTERTHANWELLSAID"
cipherText = chaoWheels(False)(plainText)
print(plainText)
print(cipherText)
print(
chaoWheels(True)(cipherText)
)
# GENERIC -------------------------------------------------
# Just :: a -> Maybe a
def Just(x):
'''Constructor for an inhabited Maybe (option type) value.
Wrapper containing the result of a computation.
'''
return {'type': 'Maybe', 'Nothing': False, 'Just': x}
# Nothing :: Maybe a
def Nothing():
'''Constructor for an empty Maybe (option type) value.
Empty wrapper returned where a computation is not possible.
'''
return {'type': 'Maybe', 'Nothing': True}
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
'''Right to left function composition.'''
return lambda f: lambda x: g(f(x))
# concat :: [[a]] -> [a]
# concat :: [String] -> String
def concat(xs):
'''The concatenation of all the elements
in a list or iterable.
'''
def f(ys):
zs = list(chain(*ys))
return ''.join(zs) if isinstance(ys[0], str) else zs
return (
f(xs) if isinstance(xs, list) else (
chain.from_iterable(xs)
)
) if xs else []
# drop :: Int -> [a] -> [a]
# drop :: Int -> String -> String
def drop(n):
'''The sublist of xs beginning at
(zero-based) index n.
'''
def go(xs):
if isinstance(xs, (list, tuple, str)):
return xs[n:]
else:
take(n)(xs)
return xs
return lambda xs: go(xs)
# elemIndex :: Eq a => a -> [a] -> Maybe Int
def elemIndex(x):
'''Just the index of the first element in xs
which is equal to x,
or Nothing if there is no such element.
'''
def go(xs):
try:
return Just(xs.index(x))
except ValueError:
return Nothing()
return lambda xs: go(xs)
# maybe :: b -> (a -> b) -> Maybe a -> b
def maybe(v):
'''Either the default value v, if m is Nothing,
or the application of f to x,
where m is Just(x).
'''
return lambda f: lambda m: v if None is m or m.get('Nothing') else (
f(m.get('Just'))
)
# splitAt :: Int -> [a] -> ([a], [a])
def splitAt(n):
'''A tuple pairing the prefix of length n
with the rest of xs.
'''
return lambda xs: (xs[0:n], xs[n:])
# take :: Int -> [a] -> [a]
# take :: Int -> String -> String
def take(n):
'''The prefix of xs of length n,
or xs itself if n > length xs.
'''
return lambda xs: (
xs[0:n]
if isinstance(xs, (list, tuple))
else list(islice(xs, n))
)
# MAIN ---
if __name__ == '__main__':
main()
- Output:
WELLDONEISBETTERTHANWELLSAID OAHQHCNYNXTSZJRRHJBYHQKSOUJY WELLDONEISBETTERTHANWELLSAID
QBasic
DECLARE FUNCTION AlphaLeft$ (ct$, pt$, CharPos!)
DECLARE FUNCTION AlphaRight$ (ct$, pt$, CharPos!)
DECLARE FUNCTION Decode$ (Text$, ct$, pt$)
DECLARE FUNCTION Encode$ (Text$, ct$, pt$)
CLS
' Deciphering a Chaocipher-encrypted message is identical to the steps used
' for enciphering. The sole difference is that the decipherer locates the
' known ciphertext letter in the left (ct$) alphabet, with the plaintext
' letter being the corresponding letter in the right (pt$) alphabet
'
' Alphabet permuting is identical in enciphering and deciphering
' Start of Main Code
' LEFT (Cipher Text$): HXUCZVAMDSLKPEFJRIGTWOBNYQ
tLeft$ = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
' RIGHT (Plain Text$): PTLNBQDEOYSFAVZKGJRIHWXUMC
tRight$ = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
' Cipher Message (Used to verify a good encoding)
cText$ = "OAHQHCNYNXTSZJRRHJBYHQKSOUJY"
' Plain Text$ Message
pText$ = "WELLDONEISBETTERTHANWELLSAID"
PRINT " Plain Text$: "; pText$
PRINT
ctLeft$ = tLeft$
ptRight$ = tRight$
' Final Cipher Text$
eText$ = Encode$(pText$, ctLeft$, ptRight$)
PRINT " Cipher Text$: "; eText$
PRINT
IF eText$ = cText$ THEN PRINT "Successful" ELSE PRINT "Failed"
ctLeft$ = tLeft$
ptRight$ = tRight$
dText$ = Decode$(eText$, ctLeft$, ptRight$)
PRINT
PRINT " Plain Text$: "; dText$
PRINT
IF dText$ = pText$ THEN PRINT "Successful" ELSE PRINT "Failed"
END
' Left Alphabet
FUNCTION AlphaLeft$ (ct$, pt$, CharPos)
tStr$ = ct$
' 1. Shift the entire left alphabet cyclically so the ciphertext letter
' just enciphered is positioned at the zenith (i.e., position 1).
tStr$ = RIGHT$(ct$, LEN(ct$) - CharPos + 1) + LEFT$(ct$, CharPos - 1)
' 2. Extract the letter found at position zenith+1 (i.e., the letter to
' the right of the zenith), taking it out of the alphabet, temporarily
' leaving an unfilled "Hole$"
Hole$ = MID$(tStr$, 2, 1)
MID$(tStr$, 2, 1) = " "
' 3. Shift all letters in positions zenith+2 up to, and including, the
' nadir (zenith+13), moving them one position to the left
tStr$ = LEFT$(tStr$, 1) + MID$(tStr$, 3, 12) + " " + RIGHT$(tStr$, 12)
' 4. Insert the just-extracted letter into the nadir position
' (i.e., zenith+13)
MID$(tStr$, 14, 1) = Hole$
AlphaLeft$ = tStr$
END FUNCTION
' Right Alphabet
FUNCTION AlphaRight$ (ct$, pt$, CharPos)
tStr$ = pt$
' 1. Shift the entire right alphabet cyclically so the plaintext letter
' just enciphered is positioned at the zenith.
tStr$ = RIGHT$(tStr$, LEN(tStr$) - CharPos + 1) + LEFT$(tStr$, CharPos - 1)
' 2. Now shift the entire alphabet one more position to the left (i.e.,
' the leftmost letter moves cyclically to the far right), moving a new
' letter into the zenith position.
tStr$ = RIGHT$(tStr$, 25) + LEFT$(tStr$, 1)
' 3. Extract the letter at position zenith+2, taking it out of the
' alphabet, temporarily leaving an unfilled "Hole$".
Hole$ = MID$(tStr$, 3, 1)
MID$(tStr$, 3, 1) = " ":
' 4. Shift all letters beginning with zenith+3 up to, and including, the
' nadir (zenith+13), moving them one position to the left.
tStr$ = LEFT$(tStr$, 2) + MID$(tStr$, 4, 11) + " " + RIGHT$(tStr$, 12)
' 5. Insert the just-extracted letter into the nadir position (zenith+13)
MID$(tStr$, 14, 1) = Hole$
AlphaRight$ = tStr$
END FUNCTION
FUNCTION Decode$ (Text$, ct$, pt$)
tStr$ = ""
FOR t = 1 TO LEN(Text$)
Char$ = MID$(Text$, t, 1)
CharPos = INSTR(ct$, Char$)
ct$ = AlphaLeft$(ct$, pt$, CharPos)
pt$ = AlphaRight$(ct$, pt$, CharPos)
tStr$ = tStr$ + RIGHT$(pt$, 1)
NEXT
Decode$ = tStr$
END FUNCTION
FUNCTION Encode$ (Text$, ct$, pt$)
tStr$ = ""
FOR t = 1 TO LEN(Text$)
Char$ = MID$(Text$, t, 1)
CharPos = INSTR(pt$, Char$)
ct$ = AlphaLeft$(ct$, pt$, CharPos)
pt$ = AlphaRight$(ct$, pt$, CharPos)
tStr$ = tStr$ + LEFT$(ct$, 1)
NEXT
Encode$ = tStr$
END FUNCTION
Raku
(formerly Perl 6)
my @left;
my @right;
sub reset {
@left = <HXUCZVAMDSLKPEFJRIGTWOBNYQ>.comb;
@right = <PTLNBQDEOYSFAVZKGJRIHWXUMC>.comb;
}
sub encode ($letter) {
my $index = @right.first: $letter.uc, :k;
my $enc = @left[$index];
$index.&permute;
$enc
}
sub decode ($letter) {
my $index = @left.first: $letter.uc, :k;
my $dec = @right[$index];
$index.&permute;
$dec
}
sub permute ($index) {
@left.=rotate: $index;
@left[1..13].=rotate;
@right.=rotate: $index + 1;
@right[2..13].=rotate;
}
reset;
say 'WELLDONEISBETTERTHANWELLSAID'.comb».&encode.join;
reset;
say 'OAHQHCNYNXTSZJRRHJBYHQKSOUJY'.comb».&decode.join;
- Output:
OAHQHCNYNXTSZJRRHJBYHQKSOUJY WELLDONEISBETTERTHANWELLSAID
Ruby
txt = "WELLDONEISBETTERTHANWELLSAID"
@left = "HXUCZVAMDSLKPEFJRIGTWOBNYQ".chars
@right = "PTLNBQDEOYSFAVZKGJRIHWXUMC".chars
def encrypt(char)
coded_char = @left[@right.index(char)]
@left.rotate!(@left.index(coded_char))
part = @left.slice!(1,13).rotate
@left.insert(1, *part)
@right.rotate!(@right.index(char)+1)
part = @right.slice!(2,12).rotate
@right.insert(2, *part)
@left[0]
end
puts txt.each_char.map{|c| encrypt(c) }.join
- Output:
OAHQHCNYNXTSZJRRHJBYHQKSOUJY
Rust
const LEFT_ALPHABET_CT: &str = "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
const RIGHT_ALPHABET_PT: &str = "PTLNBQDEOYSFAVZKGJRIHWXUMC";
const ZENITH: usize = 0;
const NADIR: usize = 12;
const SEQUENCE: &str = "WELLDONEISBETTERTHANWELLSAID";
fn cipher(letter: &char, left: &String, right: &String) -> (usize, char) {
let pos = right.find(*letter).unwrap();
let cipher = left.chars().nth(pos).unwrap();
(pos, cipher)
}
fn main() {
let mut left = LEFT_ALPHABET_CT.to_string();
let mut right = RIGHT_ALPHABET_PT.to_string();
let ciphertext = SEQUENCE.chars()
.map(|letter| {
let (pos, cipher_char) = cipher(&letter, &left, &right);
left = format!("{}{}", &left[pos..], &left[..pos]);
left = format!("{}{}{}{}", &left[ZENITH..1], &left[2..NADIR+2], &left[1..2], &left[NADIR+2..]);
if pos != right.len() - 1 {
right = format!("{}{}", &right[pos + 1..], &right[..pos + 1]);
}
right = format!("{}{}{}{}", &right[ZENITH..2], &right[3..NADIR+2], &right[2..3], &right[NADIR+2..]);
cipher_char
})
.collect::<String>();
println!("Plaintext: {}", SEQUENCE);
println!("Ciphertext: {}", ciphertext);
}
- Output:
Plaintext: WELLDONEISBETTERTHANWELLSAID Ciphertext: OAHQHCNYNXTSZJRRHJBYHQKSOUJY
Tailspin
templates chaocipher&{left:,right:,decode:}
templates permute
def ctshift: [ $@chaocipher.ct($..last)..., $@chaocipher.ct(1..$-1)...];
def p1: $ mod 26 + 1;
def ptshift: [ $@chaocipher.pt($p1..last)..., $@chaocipher.pt(1..$p1-1)...];
..|@chaocipher: { ct: [ $ctshift(1), $ctshift(3..14)..., $ctshift(2), $ctshift(15..last)...],
pt: [ $ptshift(1..2)..., $ptshift(4..14)..., $ptshift(3), $ptshift(15..last)...] };
end permute
@: {ct:[ $left... ], pt: [ $right... ], result:[]};
$... -> #
'$@.result...;' !
when <?($decode <=0>)> do
def plain: $;
def index: $@.pt -> \[i](<=$plain> $i!\) -> $(1);
..|@.result: $@.ct($index);
$index -> permute -> !VOID
otherwise
def cipher: $;
def index: $@.ct -> \[i](<=$cipher> $i!\) -> $(1);
..|@.result: $@.pt($index);
$index -> permute -> !VOID
end chaocipher
'WELLDONEISBETTERTHANWELLSAID' -> chaocipher&{left:'HXUCZVAMDSLKPEFJRIGTWOBNYQ', right:'PTLNBQDEOYSFAVZKGJRIHWXUMC',decode:0} -> '$;
' -> !OUT::write
'OAHQHCNYNXTSZJRRHJBYHQKSOUJY' -> chaocipher&{left:'HXUCZVAMDSLKPEFJRIGTWOBNYQ', right:'PTLNBQDEOYSFAVZKGJRIHWXUMC',decode:1} -> '$;
' -> !OUT::write
- Output:
OAHQHCNYNXTSZJRRHJBYHQKSOUJY WELLDONEISBETTERTHANWELLSAID
Visual Basic .NET
Module Module1
ReadOnly L_ALPHABET As String = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
ReadOnly R_ALPHABET As String = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
Enum Mode
ENCRYPT
DECRYPT
End Enum
Function Exec(text As String, mode As Mode, Optional showSteps As Boolean = False) As String
Dim left = L_ALPHABET.ToCharArray()
Dim right = R_ALPHABET.ToCharArray()
Dim eText(text.Length - 1) As Char
Dim temp(25) As Char
For i = 0 To text.Length - 1
If showSteps Then Console.WriteLine("{0} {1}", String.Join("", left), String.Join("", right))
Dim index As Integer
If mode = Mode.ENCRYPT Then
index = Array.IndexOf(right, text(i))
eText(i) = left(index)
Else
index = Array.IndexOf(left, text(i))
eText(i) = right(index)
End If
If i = text.Length - 1 Then Exit For
'permute left
For j = index To 25
temp(j - index) = left(j)
Next
For j = 0 To index - 1
temp(26 - index + j) = left(j)
Next
Dim store = temp(1)
For j = 2 To 13
temp(j - 1) = temp(j)
Next
temp(13) = store
temp.CopyTo(left, 0)
'permute right
For j = index To 25
temp(j - index) = right(j)
Next
For j = 0 To index - 1
temp(26 - index + j) = right(j)
Next
store = temp(0)
For j = 1 To 25
temp(j - 1) = temp(j)
Next
temp(25) = store
store = temp(2)
For j = 3 To 13
temp(j - 1) = temp(j)
Next
temp(13) = store
temp.CopyTo(right, 0)
Next
Return eText
End Function
Sub Main()
Dim plainText = "WELLDONEISBETTERTHANWELLSAID"
Console.WriteLine("The original plaintext is : {0}", plainText)
Console.WriteLine(vbNewLine + "The left and right alphabets after each permutation during encryption are :" + vbNewLine)
Dim cipherText = Exec(plainText, Mode.ENCRYPT, True)
Console.WriteLine(vbNewLine + "The ciphertext is : {0}", cipherText)
Dim plainText2 = Exec(cipherText, Mode.DECRYPT)
Console.WriteLine(vbNewLine + "The recovered plaintext is : {0}", plainText2)
End Sub
End Module
- 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
V (Vlang)
type Mode = int
const(
encrypt = Mode(0)
decrypt = Mode(1)
)
const(
l_alphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
r_alphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
)
fn chao(text string, mode Mode, show_steps bool) string {
len := text.len
if text.bytes().len != len {
println("Text contains non-ASCII characters")
return ""
}
mut left := l_alphabet
mut right := r_alphabet
mut e_text := []u8{len: len}
mut temp := []u8{len: 26}
for i in 0..len {
if show_steps {
println('$left $right')
}
mut index := 0
if mode == encrypt {
index = right.index_u8(text[i])
e_text[i] = left[index]
} else {
index = left.index_u8(text[i])
e_text[i] = right[index]
}
if i == len - 1 {
break
}
// permute left
for j in index..26 {
temp[j - index] = left[j]
}
for j in 0..index {
temp[26 - index + j] = left[j]
}
mut store := temp[1]
for j in 2..14 {
temp[j - 1] = temp[j]
}
temp[13] = store
left = temp.bytestr()
// permute right
for j in index..26 {
temp[j - index] = right[j]
}
for j in 0..index {
temp[26 - index + j] = right[j]
}
store = temp[0]
for j in 1..26 {
temp[j - 1] = temp[j]
}
temp[25] = store
store = temp[2]
for j in 3..14 {
temp[j - 1] = temp[j]
}
temp[13] = store
right = temp.bytestr()
}
return e_text.bytestr()
}
fn main() {
plain_text := "WELLDONEISBETTERTHANWELLSAID"
println("The original plaintext is : $plain_text")
print("\nThe left and right alphabets after each permutation ")
println("during encryption are :\n")
cypher_text := chao(plain_text, encrypt, true)
println("\nThe ciphertext is : $cypher_text")
plain_text2 := chao(cypher_text, decrypt, false)
println("\nThe recovered plaintext is : $plain_text2")
}
- Output:
Same as Kotlin Entry
Wren
class Chao {
static encrypt { 0 }
static decrypt { 1 }
static exec(text, mode, showSteps) {
var len = text.count
if (len != text.bytes.count) Fiber.abort("Text contains non-ASCII characters.")
var left = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"
var right = "PTLNBQDEOYSFAVZKGJRIHWXUMC"
var eText = List.filled(len, "")
var temp = List.filled(26, "")
for (i in 0...len) {
if (showSteps) System.print("%(left) %(right)")
var index
if (mode == Chao.encrypt) {
index = right.indexOf(text[i])
eText[i] = left[index]
} else {
index = left.indexOf(text[i])
eText[i] = right[index]
}
if (i == len - 1) break
// permute left
for (j in index..25) temp[j-index] = left[j]
for (j in 0...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 = temp.join()
// permute right
for (j in index..25) temp[j-index] = right[j]
for (j in 0...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 = temp.join()
}
return eText.join()
}
}
var plainText = "WELLDONEISBETTERTHANWELLSAID"
System.print("The original plaintext is : %(plainText)")
System.write("\nThe left and right alphabets after each permutation ")
System.print("during encryption are :\n")
var cipherText = Chao.exec(plainText, Chao.encrypt, true)
System.print("\nThe ciphertext is : %(cipherText)")
var plainText2 = Chao.exec(cipherText, Chao.decrypt, false)
System.print("\nThe recovered plaintext is : %(plainText2)")
- 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
XPL0
include xpllib; \For StrLen, StrCopy, Print
func StrChar(Str, C);
char Str, C;
[loop [if Str(0) = 0 then return 0;
if Str(0) = C then return Str;
Str:= Str+1;
];
];
def \CMode\ ENCRYPT, DECRYPT;
char L_alphabet, R_alphabet;
proc Chao(In, Out, Mode, Show_steps);
char In, Out, Mode, Show_steps;
int Len, I, J, Index;
char Store, Left(27), Right(27), Temp(27);
[Len:= StrLen(In);
StrCopy(Left, L_alphabet);
StrCopy(Right, R_alphabet);
Temp(26):= 0;
for I:= 0 to Len-1 do
[if Show_steps then Print("%s %s\n", Left, Right);
if Mode = ENCRYPT then
[Index:= StrChar(Right, In(I)) - Right;
Out(I):= Left(Index);
]
else [Index:= StrChar(Left, In(I)) - Left;
Out(I):= Right(Index);
];
if I = Len-1 then return;
\Permute Left
for J:= Index to 26-1 do Temp(J-Index):= Left(J);
for J:= 0 to Index-1 do Temp(26-Index+J):= Left(J);
Store:= Temp(1);
for J:= 2 to 14-1 do Temp(J-1):= Temp(J);
Temp(13):= Store;
StrCopy(Left, Temp);
\Permute Right
for J:= Index to 26-1 do Temp(J-Index):= Right(J);
for J:= 0 to Index-1 do Temp(26-Index+J):= Right(J);
Store:= Temp(0);
for J:= 1 to 26-1 do Temp(J-1):= Temp(J);
Temp(25):= Store;
Store:= Temp(2);
for J:= 3 to 14-1 do Temp(J-1):= Temp(J);
Temp(13):= Store;
StrCopy(Right, Temp);
];
];
char Plain_text, Cipher_text, Plain_text2;
[L_alphabet:= "HXUCZVAMDSLKPEFJRIGTWOBNYQ";
R_alphabet:= "PTLNBQDEOYSFAVZKGJRIHWXUMC";
Plain_text:= "WELLDONEISBETTERTHANWELLSAID";
Cipher_text:= MAlloc(StrLen(Plain_text) + 1);
Plain_text2:= MAlloc(StrLen(Plain_text) + 1);
Print("The original plaintext is : %s\n", Plain_text);
Print("\nThe left and right alphabets after each permutation during encryption are :\n\n");
Chao(Plain_text, Cipher_text, ENCRYPT, true);
Print("\nThe ciphertext is : %s\n", Cipher_text);
Chao(Cipher_text, Plain_text2, DECRYPT, false);
Print("\nThe recovered plaintext is : %s\n", Plain_text2);
Release(Cipher_text);
Release(Plain_text2);
]
- 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
zkl
class Chao{
var [const private] lAlphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ",
rAlphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC";
fcn encode(text){ code(text,encodeL); }
fcn decode(text){ code(text,decodeL); }
// reset alphabets each [en|de]code and maintain re-entrancy
fcn code(text,f){ text.apply(f,Data(Void,lAlphabet),Data(Void,rAlphabet)) }
fcn [private] encodeL(letter,left,right){ // encode a letter
index:=right.index(letter);
enc :=left[index].toChar();
permute(left,right,index);
println(left.text," ",right.text," ",index);
enc
}
fcn [private] decodeL(letter,left,right){ // decode a letter
index:=left.index(letter);
dec :=right[index].toChar();
permute(left,right,index);
dec
}
fcn [private] permute(left,right,index){
left.append(left.pop(0,index)); // rotate index times
left.insert(13,left.pop(1)); // rotate [1..13] once
right.append(right.pop(0,index+1)); # rotate index+1 times, idx==25==noop
right.insert(13,right.pop(2)); // rotate [2..13] once
}
}
plainText:="WELLDONEISBETTERTHANWELLSAID";
println("The original plaintext is : ",plainText);
println("\nThe left and right alphabets after each permutation"
" during encryption are:");
cipherText:=Chao.encode(plainText);
println("\nThe ciphertext is : ",cipherText);
plainText2:=Chao.decode(cipherText);
println("\nThe recovered plaintext is : ",plainText2);
- Output:
The original plaintext is : WELLDONEISBETTERTHANWELLSAID The left and right alphabets after each permutation during encryption are: ONYQHXUCZVAMDBSLKPEFJRIGTW XUCPTLNBQDEOYMSFAVZKGJRIHW 21 ADBSLKPEFJRIGMTWONYQHXUCZV OYSFAVZKGJRIHMWXUCPTLNBQDE 10 HUCZVADBSLKPEXFJRIGMTWONYQ NBDEOYSFAVZKGQJRIHMWXUCPTL 20 QUCZVADBSLKPEHXFJRIGMTWONY NBEOYSFAVZKGQDJRIHMWXUCPTL 25 HFJRIGMTWONYQXUCZVADBSLKPE JRHMWXUCPTLNBIEOYSFAVZKGQD 13 CVADBSLKPEHFJZRIGMTWONYQXU YSAVZKGQDJRHMFWXUCPTLNBIEO 15 NQXUCVADBSLKPYEHFJZRIGMTWO BIOYSAVZKGQDJERHMFWXUCPTLN 21 YHFJZRIGMTWONEQXUCVADBSLKP RHFWXUCPTLNBIMOYSAVZKGQDJE 13 NQXUCVADBSLKPEYHFJZRIGMTWO MOSAVZKGQDJERYHFWXUCPTLNBI 12 XCVADBSLKPEYHUFJZRIGMTWONQ AVKGQDJERYHFWZXUCPTLNBIMOS 2 TONQXCVADBSLKWPEYHUFJZRIGM IMSAVKGQDJERYOHFWZXUCPTLNB 21 SKWPEYHUFJZRILGMTONQXCVADB RYHFWZXUCPTLNOBIMSAVKGQDJE 10 ZILGMTONQXCVARDBSKWPEYHUFJ LNBIMSAVKGQDJOERYHFWZXUCPT 10 JILGMTONQXCVAZRDBSKWPEYHUF LNIMSAVKGQDJOBERYHFWZXUCPT 25 RBSKWPEYHUFJIDLGMTONQXCVAZ RYFWZXUCPTLNIHMSAVKGQDJOBE 14 RSKWPEYHUFJIDBLGMTONQXCVAZ YFZXUCPTLNIHMWSAVKGQDJOBER 0 HFJIDBLGMTONQUXCVAZRSKWPEY LNHMWSAVKGQDJIOBERYFZXUCPT 7 JDBLGMTONQUXCIVAZRSKWPEYHF MWAVKGQDJIOBESRYFZXUCPTLNH 2 BGMTONQUXCIVALZRSKWPEYHFJD VKQDJIOBESRYFGZXUCPTLNHMWA 2 YFJDBGMTONQUXHCIVALZRSKWPE HMAVKQDJIOBESWRYFGZXUCPTLN 21 HIVALZRSKWPEYCFJDBGMTONQUX RYGZXUCPTLNHMFAVKQDJIOBESW 13 QXHIVALZRSKWPUEYCFJDBGMTON SWYGZXUCPTLNHRMFAVKQDJIOBE 23 KPUEYCFJDBGMTWONQXHIVALZRS NHMFAVKQDJIOBRESWYGZXUCPTL 10 SPUEYCFJDBGMTKWONQXHIVALZR NHFAVKQDJIOBRMESWYGZXUCPTL 25 OQXHIVALZRSPUNEYCFJDBGMTKW WYZXUCPTLNHFAGVKQDJIOBRMES 15 UEYCFJDBGMTKWNOQXHIVALZRSP GVQDJIOBRMESWKYZXUCPTLNHFA 12 JBGMTKWNOQXHIDVALZRSPUEYCF OBMESWKYZXUCPRTLNHFAGVQDJI 5 YFJBGMTKWNOQXCHIDVALZRSPUE JIBMESWKYZXUCOPRTLNHFAGVQD 23 The ciphertext is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID
- Programming Tasks
- Solutions by Programming Task
- 11l
- Ada
- AppleScript
- Arc
- AutoHotkey
- BASIC
- C
- C sharp
- C++
- D
- Delphi
- System.SysUtils
- EasyLang
- EMal
- F Sharp
- Factor
- Fōrmulæ
- FreeBASIC
- FutureBasic
- Go
- Groovy
- Haskell
- J
- Java
- JavaScript
- Julia
- Kotlin
- Lua
- Mathematica
- Wolfram Language
- Nim
- Objeck
- Pascal
- Perl
- Phix
- Python
- QBasic
- Raku
- Ruby
- Rust
- Tailspin
- Visual Basic .NET
- V (Vlang)
- Wren
- XPL0
- Zkl