Chaocipher: Difference between revisions
(→{{header|Kotlin}}: Combined 'encrypt' and 'decrypt' operations into a single method.) |
(Added C) |
||
Line 12: | Line 12: | ||
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. |
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. |
||
=={{header|C}}== |
|||
{{trans|Kotlin}} |
|||
<lang 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; |
|||
}</lang> |
|||
{{output}} |
|||
<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|Kotlin}}== |
=={{header|Kotlin}}== |
Revision as of 21:35, 24 April 2018
Description
The Chaocipher was invented by J.F.Byrne in 1918 and, although simple by modern cryptographic standards, does not appear to have been broken until the algorithm was finally disclosed by his family in 2010.
The algorithm is described in this paper by R.Moshe in 2010 and there is a C# implementation here.
Task
The task is to code the algorithm in your language and to test that it works with the plaintext 'WELLDONEISBETTERTHANWELLSAID' used in the paper itself.
C
<lang 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;
}</lang>
- Output:
The original plaintext is : WELLDONEISBETTERTHANWELLSAID The left and right alphabets after each permutation during encryption are : HXUCZVAMDSLKPEFJRIGTWOBNYQ PTLNBQDEOYSFAVZKGJRIHWXUMC ONYQHXUCZVAMDBSLKPEFJRIGTW XUCPTLNBQDEOYMSFAVZKGJRIHW ADBSLKPEFJRIGMTWONYQHXUCZV OYSFAVZKGJRIHMWXUCPTLNBQDE HUCZVADBSLKPEXFJRIGMTWONYQ NBDEOYSFAVZKGQJRIHMWXUCPTL QUCZVADBSLKPEHXFJRIGMTWONY NBEOYSFAVZKGQDJRIHMWXUCPTL HFJRIGMTWONYQXUCZVADBSLKPE JRHMWXUCPTLNBIEOYSFAVZKGQD CVADBSLKPEHFJZRIGMTWONYQXU YSAVZKGQDJRHMFWXUCPTLNBIEO NQXUCVADBSLKPYEHFJZRIGMTWO BIOYSAVZKGQDJERHMFWXUCPTLN YHFJZRIGMTWONEQXUCVADBSLKP RHFWXUCPTLNBIMOYSAVZKGQDJE NQXUCVADBSLKPEYHFJZRIGMTWO MOSAVZKGQDJERYHFWXUCPTLNBI XCVADBSLKPEYHUFJZRIGMTWONQ AVKGQDJERYHFWZXUCPTLNBIMOS TONQXCVADBSLKWPEYHUFJZRIGM IMSAVKGQDJERYOHFWZXUCPTLNB SKWPEYHUFJZRILGMTONQXCVADB RYHFWZXUCPTLNOBIMSAVKGQDJE ZILGMTONQXCVARDBSKWPEYHUFJ LNBIMSAVKGQDJOERYHFWZXUCPT JILGMTONQXCVAZRDBSKWPEYHUF LNIMSAVKGQDJOBERYHFWZXUCPT RBSKWPEYHUFJIDLGMTONQXCVAZ RYFWZXUCPTLNIHMSAVKGQDJOBE RSKWPEYHUFJIDBLGMTONQXCVAZ YFZXUCPTLNIHMWSAVKGQDJOBER HFJIDBLGMTONQUXCVAZRSKWPEY LNHMWSAVKGQDJIOBERYFZXUCPT JDBLGMTONQUXCIVAZRSKWPEYHF MWAVKGQDJIOBESRYFZXUCPTLNH BGMTONQUXCIVALZRSKWPEYHFJD VKQDJIOBESRYFGZXUCPTLNHMWA YFJDBGMTONQUXHCIVALZRSKWPE HMAVKQDJIOBESWRYFGZXUCPTLN HIVALZRSKWPEYCFJDBGMTONQUX RYGZXUCPTLNHMFAVKQDJIOBESW QXHIVALZRSKWPUEYCFJDBGMTON SWYGZXUCPTLNHRMFAVKQDJIOBE KPUEYCFJDBGMTWONQXHIVALZRS NHMFAVKQDJIOBRESWYGZXUCPTL SPUEYCFJDBGMTKWONQXHIVALZR NHFAVKQDJIOBRMESWYGZXUCPTL OQXHIVALZRSPUNEYCFJDBGMTKW WYZXUCPTLNHFAGVKQDJIOBRMES UEYCFJDBGMTKWNOQXHIVALZRSP GVQDJIOBRMESWKYZXUCPTLNHFA JBGMTKWNOQXHIDVALZRSPUEYCF OBMESWKYZXUCPRTLNHFAGVQDJI The ciphertext is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID
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. <lang scala>// 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")
}</lang>
- Output:
The original plaintext is : WELLDONEISBETTERTHANWELLSAID The left and right alphabets after each permutation during encryption are : HXUCZVAMDSLKPEFJRIGTWOBNYQ PTLNBQDEOYSFAVZKGJRIHWXUMC ONYQHXUCZVAMDBSLKPEFJRIGTW XUCPTLNBQDEOYMSFAVZKGJRIHW ADBSLKPEFJRIGMTWONYQHXUCZV OYSFAVZKGJRIHMWXUCPTLNBQDE HUCZVADBSLKPEXFJRIGMTWONYQ NBDEOYSFAVZKGQJRIHMWXUCPTL QUCZVADBSLKPEHXFJRIGMTWONY NBEOYSFAVZKGQDJRIHMWXUCPTL HFJRIGMTWONYQXUCZVADBSLKPE JRHMWXUCPTLNBIEOYSFAVZKGQD CVADBSLKPEHFJZRIGMTWONYQXU YSAVZKGQDJRHMFWXUCPTLNBIEO NQXUCVADBSLKPYEHFJZRIGMTWO BIOYSAVZKGQDJERHMFWXUCPTLN YHFJZRIGMTWONEQXUCVADBSLKP RHFWXUCPTLNBIMOYSAVZKGQDJE NQXUCVADBSLKPEYHFJZRIGMTWO MOSAVZKGQDJERYHFWXUCPTLNBI XCVADBSLKPEYHUFJZRIGMTWONQ AVKGQDJERYHFWZXUCPTLNBIMOS TONQXCVADBSLKWPEYHUFJZRIGM IMSAVKGQDJERYOHFWZXUCPTLNB SKWPEYHUFJZRILGMTONQXCVADB RYHFWZXUCPTLNOBIMSAVKGQDJE ZILGMTONQXCVARDBSKWPEYHUFJ LNBIMSAVKGQDJOERYHFWZXUCPT JILGMTONQXCVAZRDBSKWPEYHUF LNIMSAVKGQDJOBERYHFWZXUCPT RBSKWPEYHUFJIDLGMTONQXCVAZ RYFWZXUCPTLNIHMSAVKGQDJOBE RSKWPEYHUFJIDBLGMTONQXCVAZ YFZXUCPTLNIHMWSAVKGQDJOBER HFJIDBLGMTONQUXCVAZRSKWPEY LNHMWSAVKGQDJIOBERYFZXUCPT JDBLGMTONQUXCIVAZRSKWPEYHF MWAVKGQDJIOBESRYFZXUCPTLNH BGMTONQUXCIVALZRSKWPEYHFJD VKQDJIOBESRYFGZXUCPTLNHMWA YFJDBGMTONQUXHCIVALZRSKWPE HMAVKQDJIOBESWRYFGZXUCPTLN HIVALZRSKWPEYCFJDBGMTONQUX RYGZXUCPTLNHMFAVKQDJIOBESW QXHIVALZRSKWPUEYCFJDBGMTON SWYGZXUCPTLNHRMFAVKQDJIOBE KPUEYCFJDBGMTWONQXHIVALZRS NHMFAVKQDJIOBRESWYGZXUCPTL SPUEYCFJDBGMTKWONQXHIVALZR NHFAVKQDJIOBRMESWYGZXUCPTL OQXHIVALZRSPUNEYCFJDBGMTKW WYZXUCPTLNHFAGVKQDJIOBRMES UEYCFJDBGMTKWNOQXHIVALZRSP GVQDJIOBRMESWKYZXUCPTLNHFA JBGMTKWNOQXHIDVALZRSPUEYCF OBMESWKYZXUCPRTLNHFAGVQDJI The ciphertext is : OAHQHCNYNXTSZJRRHJBYHQKSOUJY The recovered plaintext is : WELLDONEISBETTERTHANWELLSAID