fork download
  1. /*****************************************************//**
  2.  * @brief Sample Vigenere cipher, with flexible alphabet.
  3.  *
  4.  * @file vigenere.c
  5.  * @version 0.2
  6.  * @date 16 Feb, 2012
  7.  * @author migf1 <mig_f1@hotmail.com>
  8.  * @par Language:
  9.  * ANSI C (C89)
  10.  *
  11.  * @note http://e...content-available-to-author-only...a.org/wiki/Vigen%C3%A8re_cipher.
  12.  *********************************************************
  13.  */
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <time.h>
  18.  
  19. #define SHUFFLE 1 /* set it to 0 to disable alphabet shuffling */
  20. #define MAXINPUT (1024+1)
  21.  
  22. #define pressENTER() \
  23. do{ \
  24. char mYcHAr; \
  25. printf( "press ENTER..." ); \
  26. while ( (mYcHAr=getchar()) != '\n' && mYcHAr != EOF ) \
  27. ; \
  28. }while(0)
  29.  
  30. /*
  31.  * Typedefs for passing arrays of strings as arrays of constant strings to functions.
  32.  * (this makes sure that those functions will not alter any of the array contents).
  33.  */
  34. typedef const char *const ConstString;
  35. typedef const char *const * ArrayOfConstString;
  36.  
  37.  
  38. /*********************************************************//**
  39.  * @brief Read a c-string from stdin.
  40.  * @param[in,out] s (char *) The c-string to be read.
  41.  * @return The c-string (it remains unchanged on error)
  42.  *************************************************************
  43.  */
  44. char *s_read( char *s )
  45. {
  46. int lenstr = 0;
  47.  
  48. if ( !s || !fgets(s, MAXINPUT, stdin) )
  49. return s;
  50.  
  51. lenstr = strlen(s);
  52. if ( s[ lenstr - 1 ] == '\n' )
  53. s[ lenstr -1 ] = '\0';
  54.  
  55. return s;
  56. }
  57.  
  58. /*********************************************************//**
  59.  * @brief Get the index of a given char c in a given c-string s.
  60.  * @param[in] s (const char *) The c-string to be searched.
  61.  * @param[in] c (const char ) The character to be looked for.
  62.  * @return The zero-based index of c in s, or -1 on error.
  63.  *************************************************************
  64.  */
  65. int s_cindex( const char *s, const char c )
  66. {
  67. char *cp = NULL;
  68.  
  69. if ( !s || !*s )
  70. return -1;
  71.  
  72. return (cp = strchr(s,c)) ? (int)(cp - s) : -1;
  73. }
  74.  
  75. /*********************************************************//**
  76.  * @brief Shuffle the contents of a given c-string s.
  77.  * @param[in,out] s (char *) The c-string to be shuffled.
  78.  * @return The shuffled c-string (it remains unchanged on error).
  79.  * @note It requires the constant SHUFFLE to contain an non-zero value.
  80.  *************************************************************
  81.  */
  82. char *s_shuffle( char *s )
  83. {
  84. #if SHUFFLE
  85. char *cp = NULL, c = '\0';
  86. int len = 0;
  87. int i = 0;
  88.  
  89. /* sanity check */
  90. if ( !s || !*s || (len = strlen(s)) < 2 )
  91. return s;
  92.  
  93. srand( time(NULL) );
  94.  
  95. for (cp=s; *cp; cp++)
  96. {
  97. i = rand() % len;
  98. c = *cp;
  99. *cp = s[i];
  100. s[i] = c;
  101. }
  102. #endif
  103. return s;
  104. }
  105.  
  106. /*********************************************************//**
  107.  * @brief Roatate to the left a given c-string s of length len,
  108.  * by rotby characters.
  109.  * @param[in,out] s (char *) The c-string to be rotated.
  110.  * @param[in] rotby (int) The amount of characters the c-string will be rotated by.
  111.  * @param[in] len (const int) The length of the c-string in characters,
  112.  * excluding the nil terminator.
  113.  * @return The rotated c-string (remains unchanged on error).
  114.  *************************************************************
  115.  */
  116. char *s_rotate_left( char *s, int rotby, const int len )
  117. {
  118. char *temp = NULL;
  119.  
  120. if ( !s || rotby < 1 || len < 2 || (rotby %= len) == 0 )
  121. return s;
  122.  
  123. if ( NULL == (temp = malloc( rotby * sizeof(char) )) )
  124. return s;
  125. memcpy( temp, s, rotby * sizeof(char) );
  126.  
  127. memmove( s, &s[ rotby ], (len-rotby) * sizeof(char) );
  128. memcpy( &s[ len-rotby ], temp, rotby * sizeof(char) );
  129.  
  130. free( temp );
  131. return s;
  132. }
  133.  
  134. /*********************************************************//**
  135.  * @brief Print to stdout the contents of a NULL terminated
  136.  * array of c-strings.
  137.  * @param[in] sarr (ConstString *) The NULL terminated array of c-strings.
  138.  *************************************************************
  139.  */
  140. void sarr_print( ConstString sarr[] )
  141. {
  142. int i = 0;
  143.  
  144. if ( !sarr )
  145. return;
  146.  
  147. for (i=0; sarr[i]; i++ )
  148. printf("%2d: %s\n", i, sarr[i] );
  149.  
  150. return;
  151. }
  152.  
  153. /*********************************************************//**
  154.  * @brief Free memory reserved for a NULL terminated array of c-strings.
  155.  * @param[in,out] sarr (char ***) Pointer to the NULL terminated array of c-strings.
  156.  * @remark The array pointer \a *sarr is reset to NULL (that's why it
  157.  * passed <em>by reference</em> to the function).
  158.  *************************************************************
  159.  */
  160. void sarr_free( char ***sarr )
  161. {
  162. int i = 0;
  163.  
  164. if ( !sarr || !*sarr )
  165. return;
  166.  
  167. while ( (*sarr)[i] )
  168. free( (*sarr)[i++] );
  169.  
  170. *sarr = NULL;
  171. }
  172.  
  173. /*********************************************************//**
  174.  * @brief Reserve memory for a NULL terminated array of c-strings.
  175.  * @param[in] nstrings (const int) The number of c-strings to be allocated,
  176.  * not counting the terminating NULL string.
  177.  * @param[in] lenstr (const int) The number of character to be allocated for
  178.  * each c-string, excluding the nil-terminator character.
  179.  * @return A pointer to the newly allocated memory, or NULL on error.
  180.  *************************************************************
  181.  */
  182. char **sarr_new( const int nstrings, const int lenstr )
  183. {
  184. char **sarr = NULL;
  185. int i=0;
  186.  
  187. if ( nstrings < 1 || lenstr < 1 )
  188. return NULL;
  189.  
  190. if ( NULL == (sarr = calloc( nstrings+1, sizeof(char *) )) )
  191. return NULL;
  192.  
  193. for (i=0; i < nstrings; i++)
  194. {
  195. if ( NULL == (sarr[i] = calloc( lenstr+1, sizeof(char) )) )
  196. {
  197. int j;
  198. for (j=i-1; j > -1; j--)
  199. free( sarr[j] );
  200. free( sarr );
  201. return NULL;
  202. }
  203. }
  204.  
  205. return sarr;
  206. }
  207.  
  208. /*********************************************************//**
  209.  * @brief Encrypt a character according to its corresponding Vigenere
  210.  * key-character.
  211.  * @param[in] c (const char) The character to be encrypted.
  212.  * @param[in] kc (const char) The corresponding Vigenere key-character.
  213.  * @param[in] tabrecta (ConstString *) The Vigenere tabula recta, holding all the
  214.  * alphabets.
  215.  * @return The encrypted character, or '\0' on error (if either c or kc
  216.  * is not part of the basic alphabet it is considered an error).
  217.  * @remark http://e...content-available-to-author-only...a.org/wiki/Vigen%C3%A8re_cipher
  218.  ************************************************************/
  219. char c_encrypt_vigenere( const char c, const char kc, ConstString tabrecta[] )
  220. {
  221. int ci = -1; /* index of c in the basic alphabet */
  222. int kci = -1; /* index of kc in the basic alphabet */
  223.  
  224. /* sanity checks */
  225. if ( !tabrecta || !tabrecta[0]
  226. || -1 == (ci=s_cindex( tabrecta[0], c ))
  227. || -1 == (kci=s_cindex(tabrecta[0], kc)) )
  228. return '\0';
  229.  
  230. return tabrecta[kci][ci];
  231. }
  232.  
  233. /*********************************************************//**
  234.  * @brief Decrypt a character according to its corresponding Vigenere
  235.  * key-character.
  236.  * @param[in] c (const char) The character to be decrypted.
  237.  * @param[in] kc (const char) The corresponding Vigenere key-character.
  238.  * @param[in] tabrecta (ConstString *) The Vigenere tabula recta, holding all the
  239.  * alphabets.
  240.  * @return The decrypted character, or '\0' on error (if either c or kc
  241.  * is not part of the basic alphabet it is considered an error).
  242.  * @remark http://e...content-available-to-author-only...a.org/wiki/Vigen%C3%A8re_cipher
  243.  ************************************************************/
  244. char c_decrypt_vigenere( const char c, const char kc, ConstString tabrecta[] )
  245. {
  246. int ci = -1; /* index of c */
  247. int kci = -1; /* index of kc */
  248.  
  249. /* sanity checks (including both c & kc being valid chars of basic alphabet) */
  250. if ( !tabrecta || !tabrecta[0]
  251. || -1 == (ci=s_cindex(tabrecta[0], c))
  252. || -1 == (kci=s_cindex(tabrecta[0], kc)) )
  253. return '\0';
  254.  
  255. ci = s_cindex(tabrecta[kci], c); /* index of c in the kci'th alphabet */
  256. return tabrecta[0][ci]; /* ci'th char in the basic alphabet */
  257. }
  258.  
  259. /*********************************************************//**
  260.  * @brief Encrypt a c-string according to a Vigenere key c-string.
  261.  * @param[in,out] s (char *) The c-string to be encrypted.
  262.  * @param[in] skey (const char *) The Vigenere key c-string.
  263.  * @param[in] tabrecta (ConstString *) The Vigenere tabula recta, holding all the
  264.  * alphabets.
  265.  * @return The encrypted c-stsring, or NULL on error.
  266.  * @sa c_encrypt_vigenere()
  267.  ************************************************************/
  268. char *s_encrypt_vigenere(char *s, const char *skey, ConstString tabrecta[])
  269. {
  270. int i = 0; /* to parse s & skey */
  271.  
  272. /* sanity checks */
  273. if ( !s || !*s || !skey || !*skey || !tabrecta || strlen(s) != strlen(skey) )
  274. return NULL;
  275.  
  276. for (i=0; s[i]; i++)
  277. {
  278. s[i] = c_encrypt_vigenere(s[i], skey[i], (ArrayOfConstString)tabrecta);
  279. if ( '\0' == s[i] )
  280. return NULL;
  281. }
  282.  
  283. return s;
  284.  
  285. }
  286.  
  287. /*********************************************************//**
  288.  * @brief Decrypt a c-string according to a Vigenere key c-string.
  289.  * @param[in,out] s (char *) The c-string to be decrypted.
  290.  * @param[in] skey (const char *) The Vigenere key c-string.
  291.  * @param[in] tabrecta (ConstString *) The Vigenere tabula recta, holding all the
  292.  * alphabets.
  293.  * @return The decrypted c-stsring, or NULL on error.
  294.  * @sa c_decrypt_vigenere()
  295.  ************************************************************/
  296. char *s_decrypt_vigenere( char *s, const char *skey, ConstString tabrecta[] )
  297. {
  298. int i = 0; /* to parse s & skey */
  299.  
  300. /* sanity checks */
  301. if ( !s || !*s || !skey || !*skey || !tabrecta || strlen(s) != strlen(skey) )
  302. return NULL;
  303.  
  304. for (i=0; s[i]; i++)
  305. if ( '\0' == (s[i] = c_decrypt_vigenere(s[i], skey[i], tabrecta)) )
  306. return NULL;
  307. return s;
  308.  
  309. }
  310.  
  311. /*********************************************************//**
  312.  * @brief Create & fill the Vigenere tabula recta (table of alphabets).
  313.  *
  314.  * @param[in,out] tabrecta (char ***) Pointer to an array of c-strings (tabula
  315.  * recta) to be created & filled-in. If the array is
  316.  * created successfully, its last c-string will be a
  317.  * NULL string (NULL terminated array of c-strings).
  318.  * @param[in] ab (const char *) A c-string to be used as basic
  319.  * alphabet (see notes).
  320.  * @param[in] cstart (const char) The 1st character in the basic alphabet
  321.  * (see notes).
  322.  * @param[in] ablen (cont int) The basic alphabet length, in characters
  323.  * (see notes).
  324.  *
  325.  * @return The length of the newly created basic alphabet in
  326.  * characters, excluding the nil-terminator, or 0 on
  327.  * error. Since tabula recta is a square table, the
  328.  * return value of the function equals also to the
  329.  * number of c-string alphabets created, excluding the
  330.  * final NULL string.
  331.  *
  332.  * @note You may use this function differently depending on
  333.  * the arguments you pass to it. If you specify a valid,
  334.  * non-empty, c-string as the 2nd argument, then it is
  335.  * used as the basic alphabet and the rest of the
  336.  * arguments are ignored.
  337.  * However, if you pass the 2nd argument as NULL or as
  338.  * an empty c-string, then the basic alphabet is
  339.  * constructed from consecutive characters in the
  340.  * current ASCII table, starting from character \a
  341.  * cstart up to character <em>(cstart + ablen-1)</em>.
  342.  * Please note that in this case, the zero character
  343.  * '\0' is not allowed (the function returns error).
  344.  * In general, you should never include the zero
  345.  * character in your basic alphabet.
  346.  *************************************************************
  347.  */
  348. int tabrecta_make(
  349. char ***tabrecta, const char *ab, const char cstart, const int ablen )
  350. {
  351. int i, len = 0;
  352.  
  353. /* sanity check */
  354. if ( !tabrecta )
  355. return 0;
  356.  
  357. /* when ab exists and it is not an empty c-string */
  358. if ( ab && *ab )
  359. {
  360. /* reserve memory for the tablula recta */
  361. len = strlen( ab );
  362. if ( NULL == (*tabrecta = sarr_new(len, len)) )
  363. return 0;
  364.  
  365. /* copy the basic alphabet ab to the 1st string of the tabula recta */
  366. strcpy( (*tabrecta)[0], ab );
  367. s_shuffle( (*tabrecta)[0] );
  368.  
  369. /* remaining strings have basic alphabet rotated by 1 char at a time */
  370. for (i=1; (*tabrecta)[i]; i++) {
  371. strcpy( (*tabrecta)[i], (*tabrecta)[0] );
  372. s_rotate_left( (*tabrecta)[i], i, len );
  373. }
  374. }
  375.  
  376. /* when ab is NULL or empty, make alphabet from cstart to (cstart+ablen-1) */
  377. else if (cstart > '\0' && ablen > 0 && cstart + ablen - 1 < 257)
  378. {
  379. /* reserve memory for the tablula recta */
  380. len = ablen;
  381. if (NULL == (*tabrecta = sarr_new(len, len)) )
  382. return 0;
  383.  
  384. /* construct the basic alphabet into the 1st string of tabula recta */
  385. for (i=0; i < len; i++)
  386. (*tabrecta)[0][i] = cstart + i;
  387. s_shuffle( (*tabrecta)[0] ); /* shuffle the alphabet */
  388.  
  389. /* remaining strings have basic alphabet rotated by 1 char at a time */
  390. for (i=1; (*tabrecta)[i]; i++) {
  391. strcpy( (*tabrecta)[i], (*tabrecta)[0] );
  392. s_rotate_left( (*tabrecta)[i], i, len );
  393. }
  394. }
  395.  
  396. /* error */
  397. else
  398. return 0;
  399.  
  400. return len;
  401. }
  402.  
  403. /*********************************************************//**
  404.  *
  405.  *************************************************************
  406.  */
  407. int main( void )
  408. {
  409. char **tabrecta = NULL; /* Vigenere tabula recta */
  410. int ablen = 0; /* length of basic alphabet */
  411. char text[ MAXINPUT ] = {'\0'}; /* text to be encrypted */
  412. char vigkey[ MAXINPUT ] = {'\0'}; /* Vigenere key */
  413.  
  414. /* create the Vigenere tabula recta, with alphabet from '\t' to ASCII(254) */
  415. if ( 0 == (ablen=tabrecta_make( &tabrecta, NULL, '\t', 246 )) ) {
  416. puts("\nTabula recta initialization failed!");
  417. goto exit_failure;
  418. }
  419. printf("Alphabet (%d chars):\n%s\n\n", ablen, tabrecta[0] );
  420.  
  421. /* get the text to be encrypted */
  422. printf("Text to be encrypted: ");
  423. if ( *s_read(text) == '\0' ) {
  424. puts("\nempty text was given, nothing to do!");
  425. goto exit_failure;
  426. }
  427.  
  428. /* get a valid Vigenere key string */
  429. do {
  430. printf("Enter the key-string: ");
  431. s_read(vigkey);
  432. } while( strlen(vigkey) != strlen(text) );
  433.  
  434. /* encrypt given text with the given Vigenere key */
  435. if ( NULL == s_encrypt_vigenere(text, vigkey, (ArrayOfConstString)tabrecta) ) {
  436. puts("\tencryption error (perhaps an invalid char was found in text)");
  437. goto exit_failure;
  438. }
  439. printf("\nEncrypted text: %s\n", text );
  440.  
  441. /* decrypt given text using given Vigenere key */
  442. if ( NULL == s_decrypt_vigenere(text, vigkey, (ArrayOfConstString)tabrecta) ) {
  443. puts("\tdecryption error (perhaps an invalid char was found in text)");
  444. goto exit_failure;
  445. }
  446. printf("Decrypted text: %s\n\n", text );
  447.  
  448. sarr_free( &tabrecta );
  449. pressENTER();
  450. exit( EXIT_SUCCESS );
  451.  
  452. exit_failure:
  453. sarr_free( &tabrecta );
  454. pressENTER();
  455. exit( EXIT_FAILURE );
  456. }
  457.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty