Click for homepage
← SpellMaster
← Algorithm
  
BASIC →
  
2. SpellMaster in C-language
Michael Meyer — 29 July 2022 (22:54)

The second one to solve the problem independently is Michael Meyer, a programmer in the United States. His solution is in the C-language and closely follows the recovered code, using MOD 28 instead of MOD 26. Note the use of
signed char
for the calculation of the
key
. Without the prefix '
signed
' it may not behave correctly on certain compilers and/or platforms.

Download
C-code
     #include <stdio.h>
     #include <string.h>
     
     /* https://www.cryptomuseum.com/crypto/franklin/spellmaster/code.htm */
     
     /* definitions */
     #define CODEWORDSIZE 8
     #define WORDBUFSIZE 26
     
     void StoreCodeWord(char *);
     void InitCodeWord(void);
     void init_decode_key(void);
     void prepare_input(void);
     void EncodeWord(void);
     void DecodeWord(void);
     void DoCipher(int dir);
     
     /* global variables */
     char CodeWord[CODEWORDSIZE + 1];
     char WorkWord[WORDBUFSIZE + 1];
     char word_buf[WORDBUFSIZE + 1];
     
     char EncodeXlate[28] = {
         7,   /* 00 (A) */
         14,  /* 01 (B) */
         22,  /* 02 (C) */
         0,   /* 03 (D) */
         18,  /* 04 (E) */
         12,  /* 05 (F) */
         9,   /* 06 (G) */
         17,  /* 07 (H) */
         13,  /* 08 (I) */
         4,   /* 09 (J) */
         3,   /* 10 (K) */
         6,   /* 11 (L) */
         1,   /* 12 (M) */
         23,  /* 13 (N) */
         10,  /* 14 (O) */
         19,  /* 15 (P) */
         2,   /* 16 (Q) */
         16,  /* 17 (R) */
         15,  /* 18 (S) */
         20,  /* 19 (T) */
         8,   /* 20 (U) */
         24,  /* 21 (V) */
         5,   /* 22 (W) */
         25,  /* 23 (X) */
         11,  /* 24 (Y) */
         21,  /* 25 (Z) */
         26,  /* 26 ([) */
         27,  /* 27 (\) */
     };
     
     char DecodeXlate[28]; /* set up by init_decode_key */
     
     void
     StoreCodeWord(char *word)
     {
         int i, j = 0, length = strlen(word);
     
         for (i = 0; i < CODEWORDSIZE; i++) {
             char letter = word[j];
             if (letter >= 'a' && letter <= 'z')
                 letter -= ('a' - 'A');
             if (letter >= 'A' && letter <= 'Z') {
                 CodeWord[i] = letter;
             } else {
                 i--;
             }
             j++;
             if (j >= length)
                 j = 0;
         }
         CodeWord[CODEWORDSIZE] = '\0';
     }
     
     void
     InitCodeWord(void)
     {
         StoreCodeWord("FRANKLIN");
     }
     
     void
     EncodeWord(void)
     {
         DoCipher(0);
     }
     
     void
     DecodeWord(void)
     {
         DoCipher(1);
     }
     
     void
     prepare_input(void)
     {
         int i, length = strlen(word_buf);
         for (i = 0; i < length; i++) {
             if (word_buf[i] == '-' || word_buf[i] == ' ')
                 word_buf[i] = '[';
             else if (word_buf[i] == '?')
                 word_buf[i] = '\\';
             else if (word_buf[i] >= 'a' && word_buf[i] <= 'z')
                 word_buf[i] -= ('a' - 'A');
     
             if (word_buf[i] > '\\' || word_buf[i] < 'A')
                 word_buf[i] = '[';
         }
     }
     
     int
     mod(int n, int m)
     {
         if (n > 0)
             return n % m;
     
         while (n < 0)
             n += m;
     
         return n;
     }
     
     void
     DoCipher(int dir)
     {
         int i, j, length;
         char tempcode[CODEWORDSIZE + 1];
     
         length = strlen(word_buf);
     
         /* Convert input text to 0-27 range */
         for (i = 0; i < length; i++) {
             if (dir == 0) {
                 word_buf[i] = EncodeXlate[word_buf[i] - 'A'];
             } else {
                 word_buf[i] = word_buf[i] - 'A';
             }
         }
     
         /* Take copy of the key */
         (void) strcpy(tempcode, CodeWord);
     
         /* Encrypt or decrypt the text */
         for (i = 0; i < length; i++) {
             signed char key = 0;
             /* Calculate key */
             for (j = 0; j < CODEWORDSIZE; j++) {
                 key += (tempcode[j] - 'A');
             }
             key = mod(key, 28);
     
             /* Apply key */
             WorkWord[i] = mod(key - word_buf[i], 28);
     
             /* Modify key */
             if (dir == 0) {
                 key = mod(key + word_buf[i], 28);
             } else {
                 key = mod(key + WorkWord[i], 28);
             }
             for (j = 1; j < CODEWORDSIZE; j++) {
                 tempcode[j - 1] = tempcode[j];
             }
             tempcode[CODEWORDSIZE - 1] = key;
         }
     
         /* Convert result back to ASCII range */
         for (i = 0; i < length; i++) {
             if (dir == 0) {
                 WorkWord[i] += 'A';
             } else {
                 WorkWord[i] = DecodeXlate[(int) WorkWord[i]] + 'A';
             }
             WorkWord[length] = '\0';
         }
     
         for (i = 0; i < length; i++) {
             if (WorkWord[i] == '[')
                 WorkWord[i] = '-';
             else if (WorkWord[i] == '\\')
                 WorkWord[i] = '?';
         }
         printf("%scoding result: %s\n", !dir ? "En" : "De", WorkWord);
     }
     
     void
     init_decode_key(void)
     {
         int i, j;
         for (i = 0; i < 28; i++) {
             for (j = 0; j < 28; j++) {
                 if (EncodeXlate[j] == i)
                     break;
             }
             DecodeXlate[i] = j;
         }
     }
     
     int
     main(int argc, char **argv)
     {
         const char *const usage = "usage: %s [DE] [key] [plaintext]\n";
         char key[CODEWORDSIZE + 1];
     
         if (argc < 4) {
             printf(usage, argv[0]);
             return 0;
         }
     
         init_decode_key();
     
         (void) strncpy(key, argv[2], CODEWORDSIZE);
         StoreCodeWord(key);
     
         (void) strncpy(word_buf, argv[3], WORDBUFSIZE);
         prepare_input();
     
         if (*argv[1] == 'D') {
             DecodeWord();
         } else if (*argv[1] == 'E') {
             EncodeWord();
         } else {
             printf(usage, argv[0]);
             return 0;
         }
         
         return 0;
     
    
Further information
Any links shown in red are currently unavailable. If you like the information on this website, why not make a donation?
Crypto Museum. Created: Friday 29 July 2022. Last changed: Wednesday, 03 August 2022 - 19:53 CET.
Click for homepage